How to get complete response for Groovy RestClient failed response - groovy

Currently, I'm getting HttpResponseException, which has only statusCode.
How can I get complete body of response?
Here is code I'm using
restClient = new RESTClient("http://${Server}")
try {
HttpResponseDecorator resp = restClient.post(path,body,requestContentType)
as HttpResponseDecorator
return JSONObject.fromObject(resp.getData()).get("topKey","");
}
catch (HttpResponseException e) {
error(e.toString())
}
And it only output this:
[oaf.error] groovyx.net.http.HttpResponseException: Internal Server Error

Add custom failed response handler:
restClient = new RESTClient("http://${Server}")
restClient.handler.failure = { resp, data ->
resp.setData(data)
String headers = ""
resp.headers.each {
headers = headers+"${it.name} : ${it.value}\n"
}
throw new HttpResponseException(resp.getStatus(),"HTTP call failed. Status code: ${resp.getStatus()}\n${headers}\n"+
"Response: "+(resp as HttpResponseDecorator).getData())
}

Actually, you can extract the full response from the exception thrown. For example if your caught exception is e and response body JSON should contain a field called myCustomErrorCode, you can check its value by looking at e.response.data.myCustomErrorCode in addition to e.statusCode.

Related

Problem with Post json data on flask server

i'm setting up a flask server and i would like to do HTTP POST request with a json content-type from android application.
for my purpose i only need to get json data from different client.
one of these client is an android application and it basically do an http post in the server.
the code of android post request is :
public void SendHttp(View view){
new Thread(new Runnable() {
#Override
public void run() {
StringBuffer stringBuffer = new StringBuffer("");
BufferedReader bufferedReader = null;
final String lte_url="http://192.168.1.8:5000/data_center/lte";
HttpPost httpPost = new HttpPost();
try {
HttpClient httpClient = new DefaultHttpClient();
URI uri = new URI("http://192.168.1.8:5000/data_center/lte");
httpPost.addHeader(new BasicHeader(HTTP.CONTENT_TYPE,"application/json"));
httpPost.setURI(uri);
JSONObject send_ = json_lte;
txtSend.setText(""+send_.toString(2));
StringEntity entity = new StringEntity("{"+
"\"date\":"+"\""+send_.getString("Date")+","+
"\"Ping\":"+send_.getString("Ping")+","+
"\"Download\":"+send_.getString("Download")+","+
"\"Upload\":"+send_.getString("Upload")+","+
"\"Latitude\":"+send_.getString("Latitude")+","+
"\"Longitude\":"+send_.getString("Longitude")+","+
"\"Type\":"+send_.getString("Type")+","+
"\"RsRq\":"+send_.getString("RsRq")+","+
"\"RsRp\":"+send_.getString("RsRp")+","+
"\"SINR\":"+send_.getString("SINR")+","+
"\"Bandwidth\":"+send_.getString("Bandwidth")+
"}");
txtSend.setText(entity.toString());
httpPost.setEntity(entity);
HttpResponse httpResponse = httpClient.execute(httpPost);
} catch (some Exeption...)}
}
}).start();
the only output of the flask server is it
Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.1.237 - - [23/Jul/2019 22:47:58] "POST /data_center/lte HTTP/1.1" 201 -
the code about the server is :
#app.route('/data_center/lte',methods=['POST'])
def post_LTE_data():
try:
data = request.get_json(force=True)
packet = {
'date': data['Date'],
'ping': data['Ping'],
'download': data['Download'],
'upload': data['Upload'],
'latitude': data['Latitude'],
'longitude': data['Longitude'],
'type': data['Type'],
'RsRq': data['RsRq'],
'RsRp': data['RsRp'],
'SINR': data['SINR'],
'bandwidth': data['Bandwidth']
}
lte.append(packet)
return f"OK", 200
except Exception or JsonError as exc:
print(str(exc))
return "some problem"+str(exc), 201
It seems that you have to configure your logging module. You can replace the Python code print(str(exc)) with app.logger.error(str(exc)) to see if it produces some output. You can click here to find some useful code.
By the way, you can take a look at the content received by your Android client because it should receive the response "some problem"+str(exc).
I do not know much about Android code, but it seems that you are dealing with a wrong JSON string. The right format is as below:
{
"foo":"bar",
"good":"bad"
}
In your Android code, you might have to replace
"\"date\":"+"\""+send_.getString("Date")+","
to
"\"date\":"+"\""+send_.getString("Date")+"\","
The above rule should be applied to all lines in the JSON string. Be careful about the symbol "", and you have to make sure that the data during POST is a valid JSON string. Also, I suggest you use another way like utilizing some libraries to build JSON strings to avoid typos.

Getting CustomerVisionErrorException: Operation returned an invalid status code "BadRequest"

Im trying to use Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction feature by submitting an image by using pickphoto cross media and geting a result of a predicition. I have tried to pass the image as url or a stream and keep getting a badrequest. I know that I have the correct prediction key and endpoint because i works for training telling me is the way I pass the image into the method. What is the correct way to transform the image from Cross Media pick photo package into the
private async void UplodatePictureButton_Clicked(object sender, EventArgs e)
{
await CrossMedia.Current.Initialize();
MediaFile file;
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("No upload", "Picking a photo is not supported", "OK");
return;
}
file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
{
return;
}
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
return stream;
});
// Create the Api, passing in the training key
CustomVisionTrainingClient trainingApi = new CustomVisionTrainingClient()
{
ApiKey = trainingKey,
Endpoint = SouthCentralUsEndpointTraining
};
var projects = trainingApi.GetProjects();
var project = projects.FirstOrDefault(p => p.Name == "Car");
CustomVisionPredictionClient endpoint = new CustomVisionPredictionClient()
{
ApiKey = predictionKey,
Endpoint = SouthCentralUsEndpointPrediction
};
var result = endpoint.ClassifyImageUrl(project.Id, project.Name, new Microsoft.Azure.CognitiveServices.Vision.CustomVision.Prediction.Models.ImageUrl(file.Path));
foreach (var c in result.Predictions)
{
Console.WriteLine($"\t{c.TagName}: {c.Probability:P1}");
}
}
Unhandled Exception:
Microsoft.Azure.CognitiveService.Vision.CustomerVision.Prediction.Models.CustomVisionErrorException: Operation returned an invalid status code "BadRequest"
Expect a prediction.
Here is the picture of the code:
code
Here is the picture of the problem:
problem
I got the same "Bad Request Message" while trying to do a endpoint.DetectImage(projectId, iteractionName, stream). The thing is that last week it was working Perfect. I have noticed that it only happens with large images arround 2 mb

Node-red "no response object"

I'm trying to create a http get node that takes form data and then creates an http post to another web site using a rest API. I'm able to get the http call to return the correct payload however the http response node is giving a "no response object" error in the debug tab and the client never returns. Do I specifically need to do something to pass the response object so the call sends the correct response object to the http response node?
Here is the flow:
[{"id":"7011e7a9.8fee18","type":"http request","name":"","method":"use","ret":"obj","url":"","x":499,"y":84,"z":"51693a88.ae96c4","wires":[["efea497c.1015b8"]]},{"id":"589f2a18.a760d4","type":"function","name":"","func":"var myprocess = context.global.process;\nmyprocess.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\nvar dev_url = \"https://website.com:22411/central/api/qracore/browses?browseId=mfg:gp239\";\n \nvar msg = {\n \"method\" : \"GET\",\n \"url\" : dev_url,\n \"headers\" : {\n \"Authorization\": \"Basic abWZnQHFhZC5jb206=\",\n \"Origin\" : \"mybox.com\"\n }\n};\n \nreturn msg;","outputs":1,"noerr":0,"x":323,"y":154,"z":"51693a88.ae96c4","wires":[["7011e7a9.8fee18"]]},{"id":"9f65b624.609a48","type":"debug","name":"","active":true,"console":"false","complete":"payload","x":810,"y":211,"z":"51693a88.ae96c4","wires":[]},{"id":"38e4c04d.c71b4","type":"http in","name":"","url":"/workOrders","method":"get","swaggerDoc":"","x":152,"y":190,"z":"51693a88.ae96c4","wires":[["589f2a18.a760d4"]]},{"id":"e5ee54b2.1a11a8","type":"http response","name":"","x":770,"y":96,"z":"51693a88.ae96c4","wires":[]},{"id":"efea497c.1015b8","type":"function","name":"","func":"var newMsg = { payload: msg.payload };\nreturn newMsg;","outputs":1,"noerr":0,"x":582,"y":214,"z":"51693a88.ae96c4","wires":[["e5ee54b2.1a11a8","9f65b624.609a48"]]}]
The key is to pass it from node to the other. You do that by using the req and the res from the msg to pass to the output.
var newMsg = { payload: msg.payload };
//return [msg, newMsg];
newMsg.user = msg.req.body["user"];
newMsg.req = msg.req;
newMsg.res = msg.res;
return newMsg;

Service Stack Request Filter Attribute custom Message

I am using the RequestFilterAttribute to create a custom Filter attribute that check for Autentication etc. I am responding with 401 UnAuthorized Message for logins not authenticated and for Forbiddens I am sending a 403 Forbidden. How do I sent a custom message with the 401 & 403 messages , I want to send custom messages , do i use that statusdescription ? or is there another way for me to add the custom messages?
public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
{
//Return unauthorized
res.StatusCode = (int)HttpStatusCode.Unauthorized;
res.StatusDescription = "Not Authorized";
res.EndRequest();
}
Yes the IResponse.StatusDescription is used to alter the Status Description on the HTTP Response.
You can still write to the Response if you want to send back more structured data in the HTTP Response body, e.g. this also serializes a custom ErrorResponse DTO:
var errorResponse = new ErrorResponse {
ResposneStatus = new ResposneStatus {
ErrorCode = "CustomErrorCode",
Message = "Custom Message"
}
};
res.StatusCode = (int)HttpStatusCode.Unauthorized;
res.StatusDescription = "Not Authorized";
res.WriteToResponse(req, errorResponse);

Why is HTTPBuilder basic auth not working?

The following code doesn't authenticate the user (no authentication failure happens, but the call fails due to lack of permissions):
def remote = new HTTPBuilder("http://example.com")
remote.auth.basic('username', 'password')
remote.request(POST) { req ->
uri.path = "/do-something"
uri.query = ['with': "data"]
response.success = { resp, json ->
json ?: [:]
}
}
But the following works fine:
def remote = new HTTPBuilder("http://example.com")
remote.request(POST) { req ->
uri.path = "/do-something"
uri.query = ['with': "data"]
headers.'Authorization' =
"Basic ${"username:password".bytes.encodeBase64().toString()}"
response.success = { resp, json ->
json ?: [:]
}
}
Why isn't the first one working?
Two things that I can think of off the top of my head.
The .setHeaders method requires a map. Have you tried 'Authorization' : "Basic ${"username:password".bytes.encodeBase64().toString()}" ?
If not, It's a bit more work and code, but you could user the URIBuilder as well. Generally I encapsulate to a different class
protected final runGetRequest(String endpointPassedIn, RESTClient Client){
URIBuilder myEndpoint = new URIBuilder(new URI(Client.uri.toString() + endpointPassedIn))
HttpResponseDecorator unprocessedResponse = Client.get(uri: myEndpoint) as HttpResponseDecorator
def Response = unprocessedResponse.getData() as LazyMap
return Response
}
Hope this helps
Looks like your server isn't fully HTTPBuilder-compilant. It should return 401 code (which is standart behaviour for REST servers, but non-standart for others) for HTTPBuilder to catch this status and resend authentication request. Here is written about it.

Resources