codenameone POST request BODY - java

I am using CodenameOne to send a POST request to a REST API.
It works perfectly with the GET because I do not have to pass a BODY with the message.
Please can someone tell me how to pass a BODY with my post message?
Here is the code I am using to connect ...
try {
ConnectionRequest connReq = new ConnectionRequest();
connReq.setPost(true);
connReq.addRequestHeader("Authorization", "54321);
connReq.addRequestHeader("client_id","12345");
connReq.addRequestHeader("Content-Type","application/json");
connReq.setUrl("https://myapi.com/connect");
connReq.setHttpMethod("POST");
NetworkManager.getInstance().addToQueueAndWait(connReq);
Map<String,Object> result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(connReq.getResponseData()), "UTF-8"));
return result;
}
catch(Exception err) {
System.err.println(err);
return null;
}
I have found some documentation here - but I can't quite understand what they are telling me ...
https://www.codenameone.com/javadoc/com/codename1/io/ConnectionRequest.html#buildRequestBody-java.io.OutputStream-
Thanks

If you want a standard "FORM" style post which is what you would get if you have fields in an HTML form just use addArgument as you would with GET. It will work with POST just fine.
If you want to "hardcode" your body e.g. some webservices expect JSON to be the body of the request just write it into the output stream in the buildRequestBody method you found.

Related

HTTP request being sent correctly but returns incorrect value/result

I'm trying to send an http request to bing's spell checking api using a GET request. I checked my parameters and headers on https://www.hurl.it/ and it returned a proper json with the spelling errors properly, however when I send the request from my java app it returns this json with NO spelling errors detected (therefore, text parameter HAS to be empty somehow). I'm definitely passing the correct key in the header because that part isn't sending an error and the code is 200 (success).
My string: "my funger is harting me"
My code returned:
{"_type":"SpellCheck","flaggedTokens":[]}
Hurl.it returned:
{
"_type":"SpellCheck",
"flaggedTokens":[
{
"offset":3,
"token":"funger",
"type":"UnknownToken",
"suggestions":[
{
"suggestion":"finger",
"score":0.903614003311793
}
]
},
{
"offset":13,
"token":"harting",
"type":"UnknownToken",
"suggestions":[
{
"suggestion":"hurting",
"score":0.903614003311793
}
]
}
]
}
This is my java code using Apache's HTTPClient library:
(note: "command.getAfter()" is the passed string I mentioned above. I debugged it and even hard coded a string to test it out. Same output obviously.)
HttpClient httpclient = HttpClients.createDefault();
try {
URIBuilder builder = new URIBuilder("https://api.cognitive.microsoft.com/bing/v5.0/spellcheck/");
builder.setParameter("text", command.getAfter());
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
request.setHeader("Ocp-Apim-Subscription-Key", "XXXXXXXX");
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
EDIT: It turns out the URI returned in the request object returns this:
https://api.cognitive.microsoft.com/bing/v5.0/spellcheck/?text=my+funger+is+harting+me
So the parameter is not empty? But when fed no text parameter in hurl.it, the api returns an error of no parameters. When the text parameter is a space " ", it returns an identical result to mine. Unsure what this means since the URI seems to be valid and not empty and my subscription key is working because i would get an error if it weren't...
EDIT: I'm starting to suspect the Apache library is ignoring the parameters I'm passing in HttpGet(uri). I'm unsure, but I'm going to try a different solution to send the request with a header and see what happens.
EDIT: I tried the following code below:
String url = "https://api.cognitive.microsoft.com/bing/v5.0/spellcheck/?text=" + command.getAfter().replace(" ", "+");
try {
URL request_url = new URL(url);
//URIBuilder uri = new URIBuilder("https://api.cognitive.microsoft.com/bing/v5.0/spellcheck/");
//uri.setParameter("text", command.getAfter());
HttpURLConnection con = (HttpURLConnection) request_url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Ocp-Apim-Subscription-Key", Keys.BING_SPELL_CHECK_API);
con.setConnectTimeout(100000);
con.setReadTimeout(100000);
con.setInstanceFollowRedirects(true);
String theString = IOUtils.toString(con.getInputStream(), "UTF-8");
System.out.println(theString);
} catch (IOException e) {
e.printStackTrace();
}
It returned the same result as the Apache one... :/ What else should I try?
EDIT:
This is the output of the request as well:
https://api.cognitive.microsoft.com/bing/v5.0/spellcheck/?text=my+funger+is+hartingme - [Ocp-Apim-Subscription-Key: <XXXXXXXXXXXX>]
HTTP/1.1 200 OK - en_US
{"_type": "SpellCheck", "flaggedTokens": []}
I don't get it.... Why is the json outputted empty when hurl.it returns the correct json for this same request? Is this a java issue or something?
EDIT:
I just tried UniRest's api. Exact same result... What am I doing wrong here?!
I'm so lost...
Separate Issue:
I do want to note the following: When I set the bing api's version to 7.0, I get the following error:
Received http status code 401 with message Access Denied and body {"message":"Access denied due to invalid subscription key. Make sure to provide a valid key for an active subscription.","statusCode":401}
This is not the case with v5.0. I'm getting the correct key from my Azure portal. (The page called Keys and lists 2 keys you can use and regenerate)
Answer to getting v7.0 to work:
This is not the case with v5.0. I'm getting the correct key from my Azure portal. (The page called Keys and lists 2 keys you can use and regenerate)
You get 2 keys per version. So if you are seeing 2 keys, they are likely both for v5.0. It should explicitly mention v7.0.
There should be different sections, also with different endpoints.
Use these in combination with each other to get the desired result.

How to read body of HttpServletRequest multiple times?

Basically I need to read the body of HttpServletRequest multiple times, based on my research I found that one of easiest way for doing that is by using ContentCachingRequestWrapper
Here is how I implemented it:
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
try{
MultipartRequest multipartRequest = new MultipartRequest(requestWrapper, ImageDirecoty, 1024*1024*5);
String test = requestWrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.print(test);
} catch(IOException e){
System.out.println(e.getMessage());
return;
}
FYI: I am uploading a simple file from my client to server.
Now at first it reads the request body just fine, but in the second line which I have String test = requestWrapper to read it's content and to output it to console I don't get my Ecplise console outputing me anything and I don't get any error too, I'd really appreciate if somebody tell me what am i doing wrong.
actually the easy est way to do it is to use(convert the response), to some kind of Pojo class, and then saving it to whatever you want.
here is a link to convert it to pojo
http://www.jsonschema2pojo.org/
also you can use library's like Retrofit 2.0 to make your http calls much easier.
http://square.github.io/retrofit/

setting content type in rest assured

I'm trying to invoke a rest call using rest assured. My API accepts, "application/json" as content type and I need to set in the call. I set the content type as mentioned below.
Option 1
Response resp1 = given().log().all().header("Content-Type","application/json")
.body(inputPayLoad).when().post(addUserUrl);
System.out.println("Status code - " +resp1.getStatusCode());
Option 2
Response resp1 = given().log().all().contentType("application/json")
.body(inputPayLoad).when().post(addUserUrl);
The response I get is "415" (indicates that "Unsupported media type ").
I tried invoking the same api using plain java code and it works. For some mysterious reason, I cudn't get it working through RA.
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(addUserUrl);
StringEntity input = new StringEntity(inputPayLoad);
input.setContentType("application/json");
post.setEntity(input);
HttpResponse response = client.execute(post);
System.out.println(response.getEntity().getContent());
/*
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
System.out.println("Output -- " +line);
}
I faced similar issue while working with rest-assured 2.7 version. I tried setting both the contentType and also accept to application/json but it didn't work. Adding carriage feed and new line characters at the end as the following worked for me.
RestAssured.given().contentType("application/json\r\n")
The API seems to be missing to add new line characters after Content-Type header due to which the server is not able to differentiate between the media type and the rest of the request content and hence throwing the error 415 - "Unsupported media type".
Here is the complete POST example using CONTENT_TYPE as JSON.
import io.restassured.http.ContentType;
RequestSpecification request=new RequestSpecBuilder().build();
ResponseSpecification response=new ResponseSpecBuilder().build();
#Test
public void test(){
User user=new User();
given()
.spec(request)
.contentType(ContentType.JSON)
.body(user)
.post(API_ENDPOINT)
.then()
.statusCode(200).log().all();
}
Give a try
given().contentType(ContentType.JSON).body(inputPayLoad.toString)
This might possibly be the case with your test. Try this.
https://github.com/rest-assured/rest-assured/wiki/Usage#avoid-adding-the-charset-to-content-type-header-automatically
Avoid adding the charset to content-type header automatically
By default REST Assured adds the charset header automatically. To
disable this completely you can configure the EncoderConfig like this:
RestAssured.config = RestAssured.config(config().encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false));
As mentioned in previous posts there is a method:
RequestSpecification.contentType(String value)
I did not work for me too. But after upgrade to the newest version (in this moment 2.9.0) it works. So please upgrade :)
I was facing something similar and after some time we noticed the problem was actually coming from the server side. Please check your call on Postman and see if when it's triggered you need to change it from HTML to JSON. If you need to do that, the backend may need to force the response to be in JSON format by adding its content type. Even if it's encoded in JSON you're still may need to do that.
Thats the line of code we added:
header('Content-type:application/json;charset=utf-8');
.
public function renderError($err){
header('Content-type:application/json;charset=utf-8');
echo json_encode(array(
'success' => false,
'err' => $err
));
}
And that's what was happening on the backend:
Hope that can help somehow. :)
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import static org.hamcrest.Matchers.is;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.given;
public class googleMapsGetLocation {
#Test
public void getLocation() {
RestAssured.baseURI = "https://maps.googleapis.com";
given().param("location", "-33.8670522,151.1957362")
.param("radius", "500")
.param("key", "AIzaSyAONLkrlUKcoW-oYeQjUo44y5rpME9DV0k").when()
.get("/maps/api/place/nearbysearch/json").then().assertThat()
.statusCode(200).and().contentType(ContentType.JSON)
.body("results[0].name", is("Sydney"));
}
}
For your First option can you please try adding this header too and sending the request?
.header("Accept","application/json")

How to receive raw data returned from http connection upon error

Most importantly I want to get the exceptionMessage that I am able to view as part of the data returned when I use SoapUI to make the request. I don't see anything in HttpURLConnection that includes this detailed information. Only responseCode and responseMessage, which are nice, but are lacking the description I'm looking for.
Also, does SoapUI parse this raw data into JSON and XML itself, or is there a simple way I can get it as JSON through java as well?
Thanks
The server returns HTTP headers and in most cases a body. To get the body in case of a error, you have to do something like that:
InputStream is;
if (conn.getResponseCode() / 100 == 2) { // HTTP status code 2xx, e.g. 200
is = conn.getInputStream();
// read input stream -> this is the content you wanted
} else {
is = conn.getErrorStream();
// read input stream -> contains a description of the error
// depending on header "Content-Type" you can also parse the stream
// as JSON or XML or HTML ...
}

Different results back accessing the same php json request from android and pc web browser

I am having a problem where when I put the querying URL into a web browser on my Mac the API send the data back as I am expecting but when I use the exact same URL within my app on android I get the following error: {"SC":"400","VSM":"Incorrect parameter passed on URL","VERNUM":"1.2"}. It is just a simple test to see if the database in my app is up to date. Is this an API problem or something i'm doing wrong in the app? I have no control over the API functionality so if it's a problem with that then I will have to get somebody else to sort it out. the code I am using is below.
String URL = "http://Url.com/?p=api&request=check_for_changes";
Log.v("Value", URL);
JSONObject jsonObjSend = new JSONObject();
try
{
jsonObjSend.put("dataset_version_number", 1.1);
// Output the JSON object we're sending to Logcat:
Log.v("Response", jsonObjSend.toString(2));
}
catch (JSONException e)
{
Log.i("Response", "Error happened here");
}
try
{
jsonObjRecv = HttpClient.SendHttpPost(URL, jsonObjSend);
Log.v("SC", jsonObjRecv.get("SC").toString());
}
catch (JSONException e){
}
The HttpClient object is from a class I have used many times before to just read the response from the server so i'm not going to post the code on here as it's not relevent and quite long.
The Answer come in the form of me being an idiot and trying to use a POST Request on a URL which doesnt accept JSON and only needs a GET Request. So I only need to query the URL and get the response rather than try and send the data via a POSTusing JSON.

Categories