spring-android Rest Template 401 and HttpMessageNotReadableException - spring-android

I've set my convertors like so - converters = {StringHttpMessageConverter.class, FormHttpMessageConverter.class, MappingJackson2HttpMessageConverter.class}
I assumed that it would try string first before trying to map to JSON. How do I signal to the underlying converter to not try and map to JSON as this response is a 401 Unauthorized and I would like to try and re-authenticate for my case and attempt the same operation?
Or should I just include a catch block with this specific exception to handle this?
Getting the following exception.
W/System.err: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized token 'Unauthorized': was expecting ('true', 'false' or 'null')
W/System.err: at [Source: buffer(com.android.okhttp.internal.http.HttpConnection$FixedLengthSource#f03e4ce).inputStream(); line: 2, column: 14]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Unauthorized': was expecting ('true', 'false' or 'null')
W/System.err: at [Source: buffer(com.android.okhttp.internal.http.HttpConnection$FixedLengthSource#f03e4ce).inputStream(); line: 2, column: 14]

Based on your response i.e 401 which is Unauthorized error response, set the headers to HttpEntity:
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Bearer <token id>");

Related

Swagger API structure for POST request without body parameters

POST request without body parameter gives a JSON parse error. Mentioned the error below.
API Call
api.post('notification/seen')
Error:
{"message":{"name":"SyntaxError","msg":"Unexpected token n in JSON at position 0","stack":"SyntaxError: Unexpected token n in JSON at position 0\n at JSON.parse ()\n at createStrictSyntaxError (/app/node_modules/body-parser/lib/types/json.js:158:10)\n at parse (/app/node_modules/body-parser/lib/types/json.js:83:15)\n at /app/node_modules/body-parser/lib/read.js:121:18\n at invokeCallback (/app/node_modules/raw-body/index.js:224:16)\n at done (/app/node_modules/raw-body/index.js:213:7)\n at IncomingMessage.onEnd (/app/node_modules/raw-body/index.js:273:7)\n at IncomingMessage.emit (events.js:327:22)\n at IncomingMessage.EventEmitter.emit (domain.js:486:12)\n at endReadableNT (_stream_readable.js:1327:12)\n at processTicksAndRejections (internal/process/task_queues.js:80:21)"},"level":"error","timestamp":"2021-09-28T06:29:19.577Z"}
Swagger API structure
/notification/seen:
post:
tags:
- Notification
responses:
204:
description: Update Seen Notification Success
401:
description: Access Token Missing/Expired
500:
description: Something went wrong!
If same API I call with adding dummy body as below with changing the Swagger API structure I am not getting the error.
API Call
api.post('notification/seen',{id:"data"})
Swagger API structure
/notification/seen:
post:
tags:
- Notification
parameters:
- in: body
name: body
schema:
type: object
responses:
204:
description: Update Seen Notification Success
401:
description: Access Token Missing/Expired
500:
description: Something went wrong!
And also if I change POST to GET request then also I am not getting the error.
How to fix the error with the POST request without a body parameter?

io.helidon.webserver.ServerResponse.send() throwing error on server but file downloaded on front end

Trying to write one sample for (file upload and download) error in server.
Though it downloads the file in the frontend, getting error in server.
For Routing--
WebServer.builder(getRouting()).port(8080).build().start();
private static Routing getRouting() throws Exception{
return Routing.builder().register("/filetest", JerseySupport.builder().register(FileController.class).build())
.build();
}
#RequestScoped
public class FileController {
#Context
ServerRequest req;
#Context
ServerResponse res;
#GET
#Path("/{fname}")
public void download(#PathParam("fname") String fname) {
try {
//Getting the file
java.nio.file.Path filepath = Paths.get("c:/"+fname+".txt");
ResponseHeaders headers = res.headers();
headers.contentType(io.helidon.common.http.MediaType.APPLICATION_OCTET_STREAM);
headers.put(Http.Header.CONTENT_DISPOSITION, ContentDisposition.builder()
.filename(filepath.getFileName().toString())
.build()
.toString());
res.send(filepath);
}catch(Exception e) {
}
}
Jul 29, 2021 6:20:36 PM
io.helidon.webserver.RequestRouting$RoutedRequest defaultHandler
WARNING: Default error handler: Unhandled exception encountered.
java.util.concurrent.ExecutionException: Unhandled 'cause' of this
exception encountered. at
io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:397)
at
io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:377)
at
io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:420)
at
io.helidon.webserver.jersey.ResponseWriter.failure(ResponseWriter.java:133)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at
org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at
org.glassfish.jersey.internal.Errors.process(Errors.java:292) at
org.glassfish.jersey.internal.Errors.process(Errors.java:274) at
org.glassfish.jersey.internal.Errors.process(Errors.java:244) at
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
at
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)
at
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
at
io.helidon.webserver.jersey.JerseySupport$JerseyHandler.lambda$doAccept$3(JerseySupport.java:299)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at
io.helidon.common.context.ContextAwareExecutorImpl.lambda$wrap$5(ContextAwareExecutorImpl.java:154)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834) Caused by:
io.helidon.common.http.AlreadyCompletedException: Response status code
and headers are already completed (sent to the client)! at
io.helidon.webserver.HashResponseHeaders$CompletionSupport.runIfNotCompleted(HashResponseHeaders.java:384)
at
io.helidon.webserver.HashResponseHeaders.httpStatus(HashResponseHeaders.java:251)
at io.helidon.webserver.Response.status(Response.java:122) at
io.helidon.webserver.Response.status(Response.java:48) at
io.helidon.webserver.jersey.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:81)
at
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:607)
at
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:373)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:363)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258)
... 14 more
Jul 29, 2021 6:20:36 PM
io.helidon.webserver.RequestRouting$RoutedRequest defaultHandler
WARNING: Cannot perform error handling of the throwable (see cause of
this exception) because headers were already sent
java.lang.IllegalStateException: Headers already sent. Cannot handle
the cause of this exception. at
io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:405)
at
io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:377)
at
io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:420)
at
io.helidon.webserver.jersey.ResponseWriter.failure(ResponseWriter.java:133)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at
org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at
org.glassfish.jersey.internal.Errors.process(Errors.java:292) at
org.glassfish.jersey.internal.Errors.process(Errors.java:274) at
org.glassfish.jersey.internal.Errors.process(Errors.java:244) at
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
at
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)
at
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
at
io.helidon.webserver.jersey.JerseySupport$JerseyHandler.lambda$doAccept$3(JerseySupport.java:299)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at
io.helidon.common.context.ContextAwareExecutorImpl.lambda$wrap$5(ContextAwareExecutorImpl.java:154)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834) Caused by:
io.helidon.common.http.AlreadyCompletedException: Response status code
and headers are already completed (sent to the client)! at
io.helidon.webserver.HashResponseHeaders$CompletionSupport.runIfNotCompleted(HashResponseHeaders.java:384)
at
io.helidon.webserver.HashResponseHeaders.httpStatus(HashResponseHeaders.java:251)
at io.helidon.webserver.Response.status(Response.java:122) at
io.helidon.webserver.Response.status(Response.java:48) at
io.helidon.webserver.jersey.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:81)
at
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:607)
at
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:373)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:363)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258)
... 14 more
When using Helidon MP, Jersey is responsible for sending the response.
In the code above you are using the underlying WebServer and sending a response inside the body of a JAXRS resource method, when Jersey sends the response the exception is thrown because it was already sent.
Helidon MP Multipart example
Jersey Multipart documentation

Image not loading in react native having bearer token authentication

I am having my images on a secure server. For authentication, I should provide a bearer token. If I pass it using the below format I am getting a blank image.
<Image
source={
{ uri: 'https://yourdomain.com/get-image',
headers: {
Authorization: 'Bearer xyz'
}
}
}/>
When I have checked error code onError prop in Image source it has
"nativeEvent": {"error": "Unexpected HTTP code 403"}
I have tested the request in postman it is working without any issues.(I am able to see the image)
The token is valid.
Edit1: Sending an XMLHttpRequest and taking the byte array and converting it into Base64 works just fine.
"nativeEvent": {"error": "Unexpected HTTP code 403"}
The 403 error HTTP status code meaning access to the requested resource is forbidden for some reason.
I think your token bearer is not correct

Using VBA-WEB GETJSON with cURL - errors

Does anyone (#TimHall) have suggestions on how to make a GET JSON request to a webservice using VBA-WEB in MS Access with a cURL string? I have reviewed many samples including these: Equivalent cURL in VBA? ; Using Excel to pull data from API ; and more. The cURL is this:
curl -XGET -H "Authorization: Bearer [oauth_token]" -H "Content-Type: application/hal+json" https://api.somewebsite.com/api/my/orders/selling/all?updated_start_date=2015-01-01T12:00-00:00&updated_end_date=2015-01-02T12:00-00:00
My end goal is to "get" the json and then save it to a .txt file on a local drive for use with JsonConverter.ParseJson.
Per #QHall suggestion, here is my best attempt- revised, based on this : https://vba-tools.github.io/VBA-Web/docs/ "GetJSON" section.
Private Sub GetTheOrdersJson()
Dim Client As New WebClient
Dim Url As String
Url = "https://api.somewebsite.com/api/my/orders/selling/all"
Dim Response As WebResponse
Set Response = Client.GetJson(Url)
Dim Headers As New Collection
Headers.Add WebHelpers.CreateKeyValue("Authorization", "Bearer [1234567890]")
Dim Options As New Dictionary
Options.Add "Headers", Headers
Set Response = Client.GetJson(Url, Options)
End Sub
In the Immediate Window this prints:
ERROR - WebHelpers.ParseByFormat: 11000, An error occurred during parsing
10001: Error parsing JSON:
Please set
^
Expecting '{' or '['
ERROR - WebHelpers.ParseByFormat: 11000, An error occurred during parsing
10001: Error parsing JSON:
Please set
^
Expecting '{' or '['
ERROR - WebHelpers.ParseByFormat: 11000, An error occurred during parsing
10001: Error parsing JSON:
Por favor e
^
Expecting '{' or '['
ERROR - WebHelpers.ParseByFormat: 11000, An error occurred during parsing
10001: Error parsing JSON:
Por favor e
^
Expecting '{' or '['

Alamofire Parse Response Data when validate fails

So the API I'm working with will sometimes send an error message in the response body when a request fails. This is located in response.data. Sometimes it's JSON, sometimes it's a string. I'm using the validate method so result.value is nil when an error occurs.
Is there a way of having Alamofire serialize the data from NSData to a string or for JSON to [ String : AnyObject ] like it would if the response was successful?
I would like to keep using the validate method.
EDIT:
Here's a link to a feature request I started on the Alamofire GitHub project.
https://github.com/Alamofire/Alamofire/issues/1459
There is not currently. I'm actually working on this very feature in Alamofire 4 right now. In Alamofire 3, you'll have to parse the response.data yourself if you get that validation error. In Alamofire 4, you'll at least have access to the response.data at the time of validation as well as be able to customize the Error that is generated by validation.
Most likely what the final solution will be is the ability to check in validation if you know there's going to be an error (checking response status code and headers). Then based on the type of error, you could parse the response.data to extract the error message from the server and throw a VERY SPECIFIC error from validation. This is most likely what the new system will allow. This way you could identify OAuth2 access token errors right in validation and throw your own custom error rather than having to use a convoluted system of response serializers to do it.
Swift 4
If you get an error, you can try parsing the response data as a string or as json.
import Alamofire
import SwiftyJSON
Alamofire.request("http://domain/endpoint", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil)
.validate()
.responseJSON(completionHandler: { response in
if let error = response.error {
if let data = response.data {
if let errorString = String(bytes: data, encoding: .utf8) {
print("Error string from server: \(errorString)")
} else {
print("Error json from server: \(JSON(data))")
}
} else {
print("Error message from Alamofire: \(error.localizedDescription)")
}
}
guard let data = response.result.value else {
print("Unable to parse response data")
return
}
print("JSON from server: \(JSON(data))")
})