Cannot see error message in http response in Kotlin Fuel - http

I am sending an HTTP PUT request to my Elasticsearch server using Fuel library on Kotlin. However, I cannot see an error body if the server returns 404 or 400. I am expecting to get an error message similar to the following:
{
"error": {
"root_cause": [
{
"type": "invalid_snapshot_name_exception",
"reason": "[snap1:kopya3]Invalid snapshot name [kopya3], snapshot with the same name already exists"
}
],
"type": "invalid_snapshot_name_exception",
"reason": "[snap1:kopya3]Invalid snapshot name [kopya3], snapshot with the same name already exists"
},
"status": 400
}
Here's my code:
val (request, response, result) = fullUrl
.httpPut()
.body(payload)
.responseString()
val (bytes, error) = result
print(error)
Instead what I see is:
HTTP Exception 400 Bad Request
com.github.kittinunf.fuel.core.FuelError$Companion.wrap(FuelError.kt:84)
com.github.kittinunf.fuel.core.DeserializableKt.response(Deserializable.kt:168)
com.github.kittinunf.fuel.core.requests.DefaultRequest.responseString(DefaultRequest.kt:475)
com.a.b.c.d.model.Cluster.createSnapshot(Cluster.kt:67)
com.a.b.c.d.model.Cluster.createSnapshot$default(Cluster.kt:57)
com.a.b.c.d.model.ClusterKt.main(Cluster.kt:85)
Caused by: HTTP Exception 400 Bad Request
com.github.kittinunf.fuel.core.FuelError$Companion.wrap(FuelError.kt:86)
Caused by: com.github.kittinunf.fuel.core.HttpException: HTTP Exception 400 Bad Request
com.github.kittinunf.fuel.core.requests.RequestTask.prepareResponse(RequestTask.kt:35)
com.github.kittinunf.fuel.core.requests.RequestTask.call(RequestTask.kt:47)
com.github.kittinunf.fuel.core.requests.RequestTask.call(RequestTask.kt:14)
com.github.kittinunf.fuel.core.DeserializableKt.response(Deserializable.kt:166)
com.github.kittinunf.fuel.core.requests.DefaultRequest.responseString(DefaultRequest.kt:475)
com.a.b.c.d.model.Cluster.createSnapshot(Cluster.kt:67)
com.a.b.c.d.model.Cluster.createSnapshot$default(Cluster.kt:57)
com.a.b.c.d.model.ClusterKt.main(Cluster.kt:85)
How can I see the actual error message? Thanks in advance.

I solved my problem by looking at response.data which is a bytes array. Converting it to string by String(response.data) I could see the error message.

It's really quite annoying that the default exception doesn't just print this.
I struggled with the generics on this one to pull the handler into its own function, so I thought I share my complete code here.
fun <T> genericErrorHandler(response: Response, result: Result.Failure<Exception>): T {
println("Request to url ${response.url} failed, server returned:")
println(String(response.data))
throw result.getException()
}
private fun someRequest(url: String, jsonBody: String): SomeDataFormatYouExpectOnSuccess {
val (_, response, result) = url.httpPost().header("Content-Type", "application/json; utf-8")
.header("Authorization", "") // adding some headers
.jsonBody(jsonBody)
.responseString()
return when (result) {
is Result.Failure -> genericErrorHandler(response, result)
is Result.Success -> {
val data = result.get()
gson.fromJson(data, SomeDataFormatYouExpectOnSuccess::class.java)
}
}
}

Related

MirageJS Error response not causing an error

Following the docs I've set up this handler inside routes():
this.put(
'/admin/features/error/environment/test',
// #ts-ignore
() => new Response(500, {}, { errors: ['The database went on vacation'] }),
);
Mirage does receive what I've set, sort of. Here is its response, from the browser console logs. Note that it's not an error although the 500 shows up in _bodyInit:
{
"type": "default",
"status": 200,
"ok": true,
"statusText": "",
"headers": {
"map": {
"content-type": "text/plain;charset=UTF-8"
}
},
"url": "",
"bodyUsed": false,
"_bodyInit": 500,
"_bodyText": "[object Number]"
}
Note that I need ts-ignore which is probably a clue. TS complains that new Response expects 0-2 arguments but got 3.
Try importing the Mirage Response class:
import { Response } from 'miragejs';
Otherwise, Response refers to a Fetch API Response object. This explains the type checking error and the unexpected behavior when calling the route.
After adding the import you can remove #ts-ignore and requests to the route should fail with status code 500.

DioError [DioErrorType.RESPONSE]: Http status error [405]

I am creating a post request Using Dio,
this is my FormData params,
FormData formData = FormData.fromMap({
'wallet_id': '${dropdownValue.walletId}',
'member_id': '${_loginModel.memberId}',
'draw_amount': withdrawalAmountContoller.text,
'login_password': passwordController.text,
});
then I am passing params like this,
Response response = await dio.post(url, data: params);
But I am getting an error on request,
ERROR[DioError [DioErrorType.RESPONSE]: Http status error [405]] => PATH: https://vertoindiapay.com/pay/api/withdraw
E/flutter ( 6703): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: DioError [DioErrorType.RESPONSE]: Http status error [405]
E/flutter ( 6703): #0 DioMixin._request._errorInterceptorWrapper. (package:dio/src/dio.dart:848:13)
Please help me solve this. My URL is=> https://vertoindiapay.com/pay/api/withdraw
Although this is working fine in postman,
Future<void> signUpUser() async {
final formData = {
'username': 'test1',
'password': 'abcdefg',
'grant_type': 'password',
};
try {
Dio _dio = new Dio();
_dio.options.contentType = Headers.formUrlEncodedContentType;
final responseData = await _dio.post<Map<String, dynamic>>('/token',
options: RequestOptions(
method: 'POST',
headers: <String, dynamic>{},
baseUrl: 'http://52.66.71.229/'),
data: formData);
print(responseData.toString());
} catch (e) {
final errorMessage = DioExceptions.fromDioError(e).toString();
print(errorMessage);
}
}
class DioExceptions implements Exception {
DioExceptions.fromDioError(DioError dioError) {
switch (dioError.type) {
case DioErrorType.CANCEL:
message = "Request to API server was cancelled";
break;
case DioErrorType.CONNECT_TIMEOUT:
message = "Connection timeout with API server";
break;
case DioErrorType.DEFAULT:
message = "Connection to API server failed due to internet connection";
break;
case DioErrorType.RECEIVE_TIMEOUT:
message = "Receive timeout in connection with API server";
break;
case DioErrorType.RESPONSE:
message =
_handleError(dioError.response.statusCode, dioError.response.data);
break;
case DioErrorType.SEND_TIMEOUT:
message = "Send timeout in connection with API server";
break;
default:
message = "Something went wrong";
break;
}
}
String message;
String _handleError(int statusCode, dynamic error) {
switch (statusCode) {
case 400:
return 'Bad request';
case 404:
return error["message"];
case 500:
return 'Internal server error';
default:
return 'Oops something went wrong';
}
}
#override
String toString() => message;
}
Please try passing the params as JSON encoded.
Response response = await dio.post(url, data: json.encode(params));
Hope this helps!
I had the same error, the BaseOptions was having different method name, other than POST... when i changed it back to POST it worked. Not sure if DIO package accepts using other than POST methods to call a Post method in API.
So I had this issue. So I found out that the headers you use in Postman should match the headers you are using in Dio. Like for example
headers: {
'Accept': "application/json",
'Authorization': 'Bearer $token',
},
and my Postman looks like this Postman
Apparently Dio behaves like postman when it comes to headers too so apparently if the headers from postman mis-match then it will throw an error.
Well in plain terms Dio would infer the content-type by itself just like postman would do.
Try to pass content type
final response = await Dio().post(Url,
options: Options(contentType: 'multipart/form-data'), data: formData);
This particular problem occurs when the response you expect (in JSON) doesn't match the response you are looking forward to receiving.
if this is your code,
Response response = await dio.post(url, data: params);
Check the Response model if it matches with the JSON it receives in the Postman response.
i had the same error the problem come from your server. your action to the server may be get datas [FromBody] use [FromForm] it will work. for me i resolved like that
eg public DataResponseModel UpdateFormalize([FromForm] FormalizeDto dto){
//somes code
}

gRPC server error handler golang

I want know about good practices with golang and gRPC and protobuf.
I am implementing the following gRPC service
service MyService {
rpc dosomethink(model.MyModel) returns (model.Model) {
option (google.api.http) = { post: "/my/path" body: "" };
}
}
I compiled the protobufs. In fact, the protobuf give us a httpproxy from http to grpc.
The code to implement this service:
import "google.golang.org/grpc/status"
func (Abcd) Dosomethink(c context.Context, sessionRequest *model.MyModel) (*model.Model, error) {
return nil, status.New(400,"Default error message for 400")
}
I want a 400 http error (in the http proxy) with the message "Default error message for 400", the message works, but the http error always is 500.
Do you know any post or doc about this?
You need to return empty model.Model object in order for protobufs to be able to properly serialise the message.
Try
import "google.golang.org/grpc/status"
func (Abcd) Dosomethink(c context.Context, sessionRequest *model.MyModel) (*model.Model, error) {
return &model.Model{}, status.Error(400,"Default error message for 400")
}
Error Handler:
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
return data, status.Errorf(
codes.InvalidArgument,
fmt.Sprintf("Your message", req.data),
)
For need more info about the error handling take a look below links.
https://grpc.io/docs/guides/error.html
http://avi.im/grpc-errors/

Proper error handling for Angular 2 http result [duplicate]

This question already has answers here:
Angular2 handling http response
(3 answers)
Closed 6 years ago.
I've been using the http error handling strategy used in the angular.io documentation:
getHeroes () {
return this.http.get(this._heroesUrl)
.map(res => <Hero[]> res.json().data)
.catch(this.handleError);
}
private handleError (error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
In some scenarios, instead of a JSON response I will receive a 204 status code (No Data). In this case, the error handler doesn't get invoked until failing to parse the result via res.json(), so the error passed to handleError is "error.json is not a function".
How can I interrogate the response stream to check for a 200 (OK) status code or a response header content-type of "application/json", and signal an error handler with a more relevant error message?
http .get('Some Url') .map(res => {
// If request fails, throw an Error that will be caught
if(res.statu != 200) {
throw new Error('This request has failed ' + res.status); } // If everything went fine, return the response
else {return res.json();
} })
This may help you.
This is just for understanding how to use the status from the response, you can modify according to your requirement.
Error is thrown only for non 200 code check this commit

How do I retrieve the error message thrown by Future from the server to the client?

Inside my server, I that checks some data from the database and throws an error when it's not valid. I have it like so:
//SERVER CODE:
Meteor.methods({
send: function (prefix, number, content) {
Future = Npm.require('fibers/future');
var future = new Future();
//do some validation
myReference.doSomething({
number: number,
content: content
}, function(error) {
if(error) {
future.throw("Cannot send at this time.");
} else {
future.return("SUCCESS");
}
});
return future.wait();
}
});
In the client side, I would like to get the message "Cannot send at this time." inside future.throw("Cannot send at this time.");. Hopefully I could show it inside an alert. How do I do that?
Currently, this is what I'm trying and I keep getting some undefined error.
//CLIENT CODE
Meteor.call("send", prefix, number, content, function(err, result) {
if(err) {
console.log(err);
alert(err);
} else {
console.log("SUCCESSFULLY SENT. ", result);
}
});
This is the error I get when trying to get the error message:
errorClass: Internal server error [500]
{
error: 500,
reason: "Internal server error",
details: undefined, message: "Internal server error [500]",
errorType: "Meteor.Error"…}
details: undefined
error: 500
errorType: "Meteor.Error"
message: "Internal server error [500]"reason:
"Internal server error"stack: (...)get
stack: function () { [native code] }set stack:
function () { [native code] }__proto__: Middle
How do I get the error message that I threw from future?
Use it like that: return future.throw(new Meteor.Error(400, 'ololo'))
future.throw expects an Meteor.Error instance that in it's turn contains error message itself and additionally http response code. So 400 is Bad Request response code in that case and ololo is error message.
return isn't actually necessary here but I do it every time just to be sure I don't call any code after failure.

Resources