Submit a GET or a POST to search in ElasticSearch - java

In this ElasticSearch document it explains how to submit a query:
GET /_search
{
"query": {
"match" : {
"message" : "this is a test"
}
}
}
But a GET doesn't have a body, it's just a link to get a document.
The related CURL in the documentation:
curl -X GET "localhost:9200/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"match" : {
"message" : "this is a test"
}
}
}
'
If I read the meaning of -d in CURL documentation, it says
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server,
in the same way that a browser does when a user has filled in an HTML
form and presses the submit button.
Meaning that the GET should be converted to a POST? I'm confused, from a Java program do I need to submit a GET or a POST to the ElasticSearch engine?

Elasticsearch _search endpoint does support GET and POST Request Type, as GET does not work with every programm. So you can just use POST instead.

Related

Search user by custom claim filter

I need to search user in identity server by using custom claim i.e. 'cnic' as a filter. I'm sending the following request packet in postman for this purpose but it gives me error. I'm using version 5.11.0 of identity server. Description of custom claim mapping is attached below.
custom claim mapping
postman request-response
Though you have created a local claim as cinc, in order to manage that claim value through SCIM APIs, you should have a mapping between a SCIM claim and the local claim.
Open the scim2-schema-extension.config file located in the <IS_HOME>/repository/conf/ and add the scim attribute definition before the last element of the JSON array (i.e. urn:ietf:params:scim:schemas:extension:enterprise:2.0:User should be the last JSON object)
It would be as follow. You can change the metadata appropriately.
{
"attributeURI":"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:cnic",
"attributeName":"cnic",
"dataType":"string",
"multiValued":"false",
"description":"National Identity Number.",
"required":"false",
"caseExact":"false",
"mutability":"readWrite",
"returned":"default",
"uniqueness":"none",
"subAttributes":"null",
"canonicalValues":[],
"referenceTypes":[]
}
Add the attributeName of the above-added attribute into scim2-schema-extension.config file, as a subAttribute of the urn:ietf:params:scim:schemas:extension:enterprise:2.0:User attribute (which is the last one in the file)
Then it would look likes follows.
"subAttributes":"verifyEmail askPassword employeeNumber costCenter organization division department manager pendingEmails accountLocked accountState emailOTPDisabled emailVerified failedEmailOTPAttempts failedLoginAttempts failedLoginAttemptsBeforeSuccess failedLoginLockoutCount failedPasswordRecoveryAttempts failedSMSOTPAttempts failedTOTPAttempts isLiteUser lastLoginTime lastLogonTime lastPasswordUpdateTime lockedReason phoneVerified preferredChannel smsOTPDisabled tenantAdminAskPassword unlockTime accountDisabled dateOfBirth isReadOnlyUser pendingMobileNumber forcePasswordReset oneTimePassword verifyMobile country cnic",
Restart the IS and login into the management console.
Navigate to Main menu-> Identity tab -> Claims .
Click Add under Claims.
Click Add External Claim and enter the following values. Then click on Add.
Dialect URI: urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
External Claim URI: urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:cnic (Attribute URI defined in the previous step)
Mapped Local Claim: http://wso2.org/claims/cnic
Then you can invoke the SCIM search as follows.
curl --location --request POST 'https://localhost:9443/scim2/Users/.search' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/json' \
--data-raw '{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:SearchRequest"
],
"attributes": [
"userName"
],
"filter": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:cnic eq 123456",
"domain": "PRIMARY",
"startIndex": "1",
"count": "10"
}'
Ref: Those steps are described well here

HttpMediaTypeNotAcceptableException: Could not find acceptable representation [duplicate]

This question already has answers here:
HttpMediaTypeNotAcceptableException: Could not find acceptable representation in exceptionhandler
(2 answers)
Closed 2 years ago.
I have the following controller class:
#RestController
#RequestMapping(value = "/query")
public class QueryController {
#Autowired
private QueryService queryService;
// this post API works perfectly fine
#PostMapping(value = "/submit")
public void submitQuery(#Valid #RequestBody Query query) {
queryService.submit(query);
}
// this API is throwing the error
#GetMapping(value = "/find/email/{email:.+}")
public List<Query> fetchByEmail(#PathVariable("email") String email) {
return queryService.fetchByEmail(email);
}
}
I am sending the the following cURL request:
curl -X GET http://localhost:8562/query/find/email/abc#gmail.com -H 'Content-Type: application/json'
In the debug mode, I can see the request has arrived at the controller with the expected emailId that I have sent in the request. The DAO layer search has also happened and it has returned 1 record, but the API throws the following error:
{
"timestamp": 1569655451392,
"status": 406,
"error": "Not Acceptable",
"message": "Could not find acceptable representation",
"path": "/query/find/email/abc#gmail.com"
}
Can someone please help?
Note: I am using springBootVersion = '2.0.5.RELEASE'
Edit: The GET API is the one that is throwing the error. Any request that does not have the dot character (.) works fine. The following request does not throw any error:
curl -X GET http://localhost:8562/query/find/email/abc#gmail -H 'Content-Type: application/json'
Edit-2: Attaching the debug screenshot below:
From this point, if I run the code, I get the following error:
{"timestamp":1569657676774,"status":406,"error":"Not Acceptable","message":"Could not find acceptable representation","path":"/query/find/email/rishi2893#gmail.com"}
HTTP 406 Not-Acceptable means that the server cannot produce a response in a format that the client can understand.
You have to send the Accept header so as to notify the server for the acceptable formats that your client can understand and to ensure that your server can produce such formats.
curl -H "Accept: application/json" ...
In addition to the above, when the Content-Type header is sent in a request, it specifies the media type of the request being sent from the client. A Content-Type header should be used in POST/PUT requests. It does not make sense in a GET request as you should not have a body in such requests.

Hyperledger Composer + loopback-datasource-juggler + Java: Encoding Problems

I developed a Business Network Definition with Hyperledger Composer, deployed it on a Hyperledger Fabric example-chain (running locally on a VirtualBox-installation of Ubuntu with Docker-containers) and started Composer's REST-server with composer-rest-server (and options -c [cardname] -n always -w true). Then I played a bit in the browser and all is working fine.
Now comes the problematic bit: I want to write a Java-program interacting with this REST API and somehow the API seems unable to parse my Java-sent requests. I copied the JSON-string that Java produces to the browser, ran it there and it worked fine. But if I send it programmatically I get the error (see at the end).
This is what I send through the browser
{"cId":"C_ID7","cDomain":"example.com"}
The browser tells me with CURL it should look like this
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"cId":"C_ID7","cDomain":"example.com"}' 'http://localhost:3000/api/com.example.Company'
Now I want to send the same message through Java+JSOUP with the following code:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}").execute();
The same (without the requestBody and Method.GET) works for GET-requests. ignoreContentType(true) is necessary, because JSOUP will not handle 'application/json', see here. ignoreHttpErrors(true) is necessary, to get through the Http 500 error, which conceals the true error, which I need for trouble-shooting.
So then finally what I see, when I execute the above code, is the following error:
{"error":{"statusCode":500,"name":"Error","message":"Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}","stack":"Error: Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}\n at com_example_Company.ModelBaseClass._initProperties
(/home/[user]
]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:249:17)\n
at com_example_Company.ModelBaseClass (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:60:8)\n
at com_example_Company.Model (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at com_example_Company.PersistedModel (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at new com_example_Company (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at Function.DataAccessObject.create (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:359:13)\n
at SharedMethod.invoke
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/shared-method.js:270:25)\n
at HttpContext.invoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/http-context.js:297:12)\n
at phaseInvoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/remote-objects.js:676:9)\n at runHandler
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:135:5)\n
at iterate (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at Object.async.eachSeries
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:162:9)\n
at runHandlers (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:144:13)\n
at iterate
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:157:25\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:154:25"}}
where obviously [user] is my username. So I had a look at the loopback-datasource-juggler sources and found that in model-builder.js (source on Github) instead of parsing the different properties of the string, it is given the complete string ("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"). In line 269 the builder checks whether there are dot-characters in the property-name. Since in our case the property name is the complete JSON-string, there are dots and the program fails.
Unfortunately XML does not seem to be supported at this point.
Now: How can this happen? My only guess is an encoding thing done by Java, because the same JSON works in the browser. Any ideas what could have caused this?
And one smaller issue: The error message in the code is ''Property names containing dot(s) are not supported. ' + 'Model: %s, property: %s'', but in the error I receive it says something about "dynamic property". Am I at the wrong point for searching what causes the error?
Since you have already specified 'Content-Type: application/json', you needn't have double quotes in the requestBody. The following should work:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody({\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}).execute();
the curl example is what the REST APIs (rather than merely the browser) know about the business network REST API endpoints.
for your requestBody, you will need the fully qualified class (ie meaning asset/participant/transaction class with leading namespace) - an example is :
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"$class": "org.example.biznet.SampleAsset", \
"assetId": "1", \
"value": "103300" \
}' 'http://localhost:3000/api/SampleAsset'
So yours will be something like
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"\$class\": \"org.example.biznet.SampleAsset\", \"cId\":\"C_ID7\", \"cDomain\":\"example.com\"}").execute();
I believe you also needed at least one other double-quotes (total above now : 14) and a closing curly bracket in addition.

Send binary data from nodejs (request) to java (ZipInputStream)

For some reason zip files produced on nodeJS gets rejected on a Java server where you can only use "binary" data upload.
If I post the file with Postman using binary it works fine, but when sending through nodeJS (request/request-promise/http ...etc) it does not work.
It gives:
java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:310)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
at com.ws...
The files are valid (it accepts via postman!)
Spent nearly two days on this issue. Read through tons on stack overflow post (most of them did not have proper answer in this specific topic) and googled around, but all the efforts in vain.
I kept experimenting and the only solution which seemed to work just fine is using child process and curl...
In case someone else falls into this really annoying problem:
var exec = require('child_process').exec;
var args = "-X POST \
https://mywebsite.com/zip-upload \
-H 'Authorization: Bearer gFChWxzeCIZVLM2q...WlvDB6zq2uOHfUcdX' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/zip' \
--data-binary #./data.zip";
exec('curl ' + args, function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
In my opinion, child_process is the last choice. If you have tried request or request-promise and failed, how about trying htp:
const htp = require('htp');
htp.post(
"https://mywebsite.com/zip-upload",
{ "Authorization" : "earer gFChWxzeCIZVLM2q...WlvDB6zq2uOHfUcdX"
, "Cache-Control" : "no-cache"
, "Content-Type" : "application/zip"
},
fs.createReadStream("./data.zip")
)
.then(function(response) { /* ... */ })
.catch(function(error) { /* ... */ })
;
I was facing similar problem. In my case, I was using custom value for Content-Type (e.g. - "application/abc+json") to upload a zip file via POST request in fetch(). It was working in Postman, but not in nodejs server.
I was able to get it working by adding Content-Length as header before making request via fetch().
Request headers I used - Content-Type, Content-Length, Authorization, and bunch of other API specific headers.
Hopefully this helps anyone facing issue.

This API does not support parsing form-encoded input

I tried to submit data to an endpoint but it said the data size was too large, so I changed the method to POST and received the error:
This API does not support parsing form-encoded input.
Next I changed the type to application/json, still with post and now I am getting:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}
],
"code": 400,
"message": "Parse Error"
}
}
What is the best way to post a large amount of data, i.e. 2730 bytes to an endpoint and have it handle it properly? In my case the field in question is of type Text as I am over the 500 character limit for app engine to hold in a String.
Also, as with many things, this works great on my local machine, it only gives this error on the live app engine instance.
Thanks!
Not sure if your problem is related, but I received the "This API does not support parsing form-encoded input." error when I was attempting to use curl to send a POST message like this:
curl -X POST -d '{"name": "Foo"}' http://foo.appspot.com/_ah/api/foo/1/endpoint
The problem was that I was not setting the content type. curl POSTs with Content-Type: application/x-www-form-urlencoded if it's not specified on the command line. Google cloud endpoints don't accept this content type.
When I changed the curl invocation to include the content type, it worked:
curl -X POST -d '{"name": "Foo"}' --header "Content-Type: application/json" http://foo.appspot.com/_ah/api/foo/1/endpoint

Categories

Resources