Use of charter encoding with content type in JAX-RS 2.0 - Jersey - rest

I am developing JAX-RS 2.0 client with Jersey implementation. REST API returns response with content type as 'application/json; UTF-8'
At client side, Jersey cannot recognize this content-type and throws error like
Unable to parse "Content-Type" header value: "application/json; UTF-8"
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/json; UTF-8"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:318)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:313)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:427)
If content type is "application/json" same code could process the response. I tried to search over google and some posts say that such character encoding along with content type is supported in Jersey but I didn't find it working.
Following is code I am trying with.
Client clientSaml = ClientBuilder.newBuilder().sslContext(context)
.hostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method`enter code here` stub
return true;
}
}).build();
clientSaml.register(new SAMLAuthenticator(token));
clientSaml.register(new LoggingFilter());
WebTarget target = clientSaml
.target(URL_OF_API);
Response resp = target.request(MediaType.APPLICATION_JSON).get();
System.out.println(resp.getMediaType().toString());
Does anybody had this issue before and what could be possible solution of this ?? Does any other implementation of JAX-RS support it ?

You forgot charset=:
Content-Type: application/json; charset=UTF-8
See Section 14.17 Content-Type of HTTP 1.1.

I did workaround of this issue using ClientResponseFilter
Thanks to hint suggested in Jersey and #FormParam not working when charset is specified in the Content-Type

Related

How To Preserve SOAP Headers to use with Mule 4 Web Service Consumer?

I have used an Existing WSDL to create an Experience API where I am performing several steps before either:
Passing the SOAP Request Message as-is to the Original Backend System using Mule4 Web Service Consumer or
Calling another Backend System (RESTful API) and transforming the Response to match the Expected SOAP Response Message
Sample Message
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="urn:Acme/PublicService/V1" xmlns:ns0="urn:/Acme/BasicDataPublicService/V1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<a:Action s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">urn:Acme/PublicService/V1/PublicService/SetCustomer</a:Action>
<a:MessageID xmlns:a="http://www.w3.org/2005/08/addressing">urn:uuid:4afe0693-adea-4ede-bec9-10b694708d85</a:MessageID>
<a:ReplyTo xmlns:a="http://www.w3.org/2005/08/addressing">
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo8KxyyGpakdIj8o84JOeAMsAAAAAQBkt3vfAK0C4dDgn3rAKx/iXgqYosnhKv/OHgph9cXoACQAA</VsDebuggerCausalityData>
<a:To s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">http://316.820.517.311:36990/PublicInterface/Service</a:To>
<AuthorizationToken xmlns="urn:Acme/Authorization/V1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CultureName>uk-UK</CultureName>
<OnBehalfOf i:nil="true"></OnBehalfOf>
<Password>****</Password>
<UserName>sa-ACME</UserName>
</AuthorizationToken>
</env:Header>
<env:Body>
<ns:SetCustomer>Muli-Tier Message</ns:SetCustomer>
</env:Body>
</env:Envelope>
According to Mulesoft KB; this requires additional Transformation steps in the beginning of the flow. Passing the SOAP Body is not an issue; the SOAP Header is a pickle, however. Especially since the KB document is hard-coding the values; while in my case these need to be dynamic (i.e. coming from the Original SOAP Request message).
I tried mapping the Header Parameters to a Variable as described but I cannot seem to get to it.
Option 1 Mapping the Header Elements to Children Attributes of a Variable, results in the Variable Storing Null
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: {
ns0#Action #(s#mustUnderstands: payload.headers.Action.#mustUnderstands): payload.headers.Action as String default null,
ns0#MessageID: payload.headers.MessageID as String default null,
ns0#ReplyTo: {
ns0#Address: payload.headers.ReplyTo.Address as String default null
},
VsDebuggerCausalityData: payload.headers.VsDebuggerCausalityData as String default null,
ns0#To #(s#mustUnderstands: payload.headers.To.#mustUnderstands): payload.headers.To as String default null,
AuthorizationToken: {
CultureName: payload.headers.AuthorizationToken.CultureName as String default null,
OnBehalfOf: payload.headers.AuthorizationToken.OnBehalfOf as String default null,
Password: payload.headers.AuthorizationToken.Password as String default null,
UserName: payload.headers.AuthorizationToken.UserName as String default null
}
}
Option 2 Mapping payload.headers to a Variable, results in extra tags; and losing the XML Tag attributes
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: payload.headers
It seems there is an issue with the WebService Consumer connector when generating the SOAP Envelope Header.
Instead of using the WebService Consumer Connector, try using an HTTP Request Connector passing the payload as-is.
I will come back and add more details on the answer, but here is how to solve that issue:
%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
---
headers: (payload.headers.headers mapObject (value, key) -> {
(value)
})

Vertx Web Client throwing HTTP 415 Unsupported Media Type for Multipart/form-data

This service receives the multipart request from mobile client and passes on the request to downstream service for uploading the image. I am seeing 415 Unsupported Media Type in my downstream service
private void makeRequest(HttpRequest<Buffer> httpRequest,
Promise<Object> future,
RequestContext requestContext,
RoutingContext routingContext,
Entry entry) {
MultipartForm multipartForm = MultipartForm.create();
MultiMap attributes = routingContext.request()
.formAttributes();
attributes.forEach(attribute -> {
multipartForm.attribute(attribute.getKey(), attribute.getValue());
});
routingContext.fileUploads()
.forEach(fileUpload -> {
multipartForm.binaryFileUpload(fileUpload.name(), fileUpload.fileName(),
fileUpload.uploadedFileName(), fileUpload.contentType());
});
httpRequest.sendMultipartForm(multipartForm, response -> {
handleResponse(routingContext, future, response, requestContext, entry);
});
}
Getting the below exception
javax.ws.rs.NotSupportedException: HTTP 415 Unsupported Media Type
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.getMethodRouter(MethodSelectingRouter.java:478)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.access$000(MethodSelectingRouter.java:94)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter$4.apply(MethodSelectingRouter.java:779)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.apply(MethodSelectingRouter.java:371)
API signature of my downstream service
#POST
#Timed
#Path("{userId}/{scope}/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation("Multipart upload of an image")
Can someone please guide what is wrong in my code snippet or is there any setting which needs to be enabled in vertx server or vertx web client?
Thanks,
Nitish Goyal
I was able to resolve this by explicitly setting the header
.putHeader("content-type", "multipart/form-data")

How to make a RESTful call using Basic Authentication in apache camel?

I have an apache camel application that requires sending log files to an endpoint and this requires Basic Authentication. I was able to pass the authMethod, authusername and authPassword to the url as specified in the camel documentation but the challange I'm having is that I keep getting null response from the endpoint after starting the application.
However, the same endpoint returns response code and response body using postman.
Below is my code:
from("{{routes.feeds.working.directory}}?idempotent=true")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
String fileName = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
File file = exchange.getIn().getBody(File.class);
multipartEntityBuilder.addPart("file",
new FileBody(file, ContentType.MULTIPART_FORM_DATA, fileName));
exchange.getOut().setBody(multipartEntityBuilder.build());
Message out = exchange.getOut();
int responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
log.info("response code "+responseCode);
}
})
.setHeader(Exchange.HTTP_QUERY,
constant("authMethod=Basic&authUsername="+username+"&authPassword="+password+""))
.to(TARGET_WITH_AUTH +"/"+uuid+"/files")
.log(LoggingLevel.DEBUG, "response code >>>>"+Exchange.HTTP_RESPONSE_CODE)
.log(LoggingLevel.INFO, "RESPONSE BODY ${body}")
.end();
Kindly help review and advise further
For HTTP basic authentication I use this before sending a request
<setHeader headerName="Authorization">
<constant>Basic cm9vdDpyb290</constant>
</setHeader>
cm9vdDpyb290 - Encoded Base64 root:root(username and password) string
This was fixed by using httpClient to send my requests with Basic Authentication. Apparently, authMethod in apache camel doesn't send the credentials along with the Post Request and that's why I was getting the initial 401 response code.
Thank y'all for your contributions.

Azure media service job creation fails using rest api

Trying to consume Azure media service rest api. (following the tutorial : https://learn.microsoft.com/en-us/azure/media-services/media-services-rest-get-started)
Everything works fine until the point I try to create a Job. Sending the same request as in example (except asset id and token) and getting response :
Parsing request content failed due to: Make sure to only use property names that are defined by the type
Request:
POST https://wamsdubclus001rest-hs.cloudapp.net/api/Jobs HTTP/1.1
Connection: Keep-Alive
Content-Type: application/json
Accept: application/json; odata=verbose
Accept-Charset: UTF-8
Authorization: Bearer token -> here i send real token
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
x-ms-version: 2.11
Content-Length: 458
Host: wamsdubclus001rest-hs.cloudapp.net
{
"Name":"TestJob",
"InputMediaAssets":[
{
"__metadata":{
"uri":"https://wamsdubclus001rest-hs.cloudapp.net/api/Assets('nb%3Acid%3AUUID%3A5168b52a-68ed-4df1-bac8-0648ce734ff6')"
}
}
],
"Tasks":[
{
"Configuration":"Adaptive Streaming",
"MediaProcessorId":"nb:mpid:UUID:ff4df607-d419-42f0-bc17-a481b1331e56",
"TaskBody":"<?xml version=\"1.0\" encoding=\"utf-8\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset> <outputAsset>JobOutputAsset(0)</outputAsset></taskBody>"
}
]
}
Response:
{
"error":{
"code":"",
"message":{
"lang":"en-US",
"value":"Parsing request content failed due to: Make sure to only use property names that are defined by the type"
}
}
}
It seems to be related with __metadata property. when I follow instruction from here : Creating Job from REST API returns a request property name error, the error changes:
"error":{
"code":"",
"message":{
"lang":"en-US",
"value":"Invalid input asset reference in TaskBody - "
}
}
}
Cant figure out whats wrong, thanks
Let me check on this, but it could be a couple issues that I have run into in the past.
First. Set both the Accept and Content-Type headers to:
"application/json; odata=verbose"
Next, double check that you are actually using the long underscore character on the metadata property. I've had issues where that was sending the wrong underscore character and it didn't match the property name.
Let me know if either of those helps.
It seems the issue was about "Content-Type". As I am using .net Core it was not easy to set the Conent-type as "application/json; odata=verbose".
1) Tried with RestSharp - dosnt support it, it cuts "odata=verbose" part out
2) Tried with Systsem.Net.Http.HttpClient -> Possible but difficult.
To add it as "Accept" :
MediaTypeWithQualityHeaderValue mtqhv;
MediaTypeWithQualityHeaderValue.TryParse("application/json;odata=verbose", out mtqhv);
client.DefaultRequestHeaders.Accept.Add(mtqhv);//ACCEPT header
To add it as "Content-Type" :
request.Content = new StringContent(content,
System.Text.Encoding.UTF8); //CONTENT-TYPE header -> default type will be text/html
request.Content.Headers.Clear(); // need to clear it - it will fail otherwise
request.Content.Headers.TryAddWithoutValidation("Content-Type","application/json;odata=verbose");

Akka HTTP how to POST singleRequest with Content-Type application/x-www-form-urlencoded

I stuck with sending request with Akka HTTP singleRequest(). I'm trying to deal with Stripe API and it requires application/x-www-form-urlencoded content type for the incoming requests.
I tried to use following structure of HTTP request:
val authorization = Authorization(OAuth2BearerToken("some_token"))
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = FormData(Map("email" -> HttpEntity("test_1#email.com"))).toEntity(),
protocol = HttpProtocols.`HTTP/1.1`)
)
But in the Stripe logs I see following in the Parsed Request POST Body section:
(multipart form: 162)
So the question is how to set content type to application/x-www-form-urlencoded?
The problem was related to FormData type. In order to perform application/x-www-form-urlencoded request you need to use FromData from package akka.http.scaladsl.model
So here is working example:
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = akka.http.scaladsl.model.FormData(Map("email" -> "user#email.com")).toEntity(HttpCharsets.`UTF-8`),
protocol = HttpProtocols.`HTTP/1.1`)
)