1
NOTICE UPDATE!!

The problem got solved and i added my own answer in the thread

In short, I have attempted to add the parameter "scan_id" value but since it is a POST i can't add the value directly in the url path.

using the code i already have, how would i go about modifying or adding so that the url is correct, that is, so that it accepts my POST?.

somehow i have been unable to find any examples that have helped me in figuring out how i would go about doing this..

I know how to do a POST with a payload, a GET with params. but a post with Params is very confusing to me.

Appreciate any help. (i'd like to continue using HttpUrlConnection unless an other example is provided that also tells me how to send the request and not only configuring the path.

I've tried adding it to the payload. I've tried UriBuilder but found it confusing and in contrast with the rest of my code, so wanted to ask for help with HttpUrlConnection.

URL url = new URL("http://localhost/scans/{scan_id}/launch");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("tmp_value_dont_mind_this", "432432");
        con.setRequestProperty("X-Cookie", "token=" + "43432");
        con.setRequestProperty("X-ApiKeys", "accessKey="+"43234;" + " secretKey="+"43234;");

        con.setDoInput(true);
        con.setDoOutput(true); //NOT NEEDED FOR GETS
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

                //First example of writing (works when writing a payload)
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();     

        //second attemp at writing, doens't work (wanted to replace {scan_id} in the url)
        DataOutputStream writer = new DataOutputStream(con.getOutputStream());
        writer.writeChars("scan_id=42324"); //tried writing directly
        //writer.write(payload);
        writer.close();     

Exception:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: http://localhost/scans/launch

I'd like one of the three response codes because then i know the Url is correct:

200 Returned if the scan was successfully launched. 
403 Returned if the scan is disabled. 
404 Returned if the scan does not exist. 

I've tried several urls

localhost/scans/launch, 
localhost/scans//launch, 
localhost/scans/?/launch, 
localhost/scans/{scan_id}/launch,
theLittleBox
  • 29
  • 1
  • 7
  • Refer https://stackoverflow.com/questions/14551194/how-are-parameters-sent-in-an-http-post-request – hagarwal Sep 12 '19 at 09:40
  • Are you using path parameters? `scan_id=42324` is a query parameter. In your case, the path parameter should be `http://localhost/scans/42324/launch`. – Hasitha Jayawardana Sep 12 '19 at 09:52
  • I believe i want the 42324 to be in the query. When i send the path http://localhost/scans/42324/launch the API doesn't understand it and response with a 400 response code. – theLittleBox Sep 12 '19 at 09:56

4 Answers4

1

So with the help of a friend and everyone here i solved my problem.

The below code is all the code in an entire class explained bit by bit. at the bottom you have the full class with all its syntax etc, that takes parameters and returns a string.

in a HTTP request there are certain sections. Such sections include in my case, Request headers, parameters in the Url and a Payload.

depending on the API certain variables required by the API need to go into their respective category.

My ORIGINAL URL looked like this: "http://host:port/scans/{scan_id}/export?{history_id}"
I CHANGED to: "https://host:port/scans/" + scan_Id + "/export?history_id=" + ID;

and the API i am calling required an argument in the payload called "format" with a value.

String payload = "{\"format\" : \"csv\"}";

So with my new URL i opened a connection and set the request headers i needed to set.

        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

The setDoOutput should be commented out when making a GET request.

        con.setDoInput(true);
        con.setDoOutput(true); 
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        con.setRequestProperty("X-Cookie", "token=" + token);
        con.setRequestProperty("X-ApiKeys", "accessKey="+"23243;" +"secretKey="+"45543;");

Here i write to the payload.

        //WRITING THE PAYLOAD to the http call
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();

After i've written the payload i read whatever response i get back (this depends on the call, when i do a file download (GET Request) i don't have a response to read as i've already read the response through another piece of code).

I hope this helps anyone who might encounter this thread.

public String requestScan(int scan_Id, String token, String ID) throws MalformedInputException, ProtocolException, IOException {

    try {
        String endpoint = "https://host:port/scans/" + scan_Id + "/export?history_id=" ID;
        URL url = new URL(endpoint);

        String payload= "{\"format\" : \"csv\"}";

        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

        con.setDoInput(true);
        con.setDoOutput(true);
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        con.setRequestProperty("X-Cookie", "token=" + token);
        con.setRequestProperty("X-ApiKeys", "accessKey="+"324324;" + 
                "secretKey="+"43242;");

        //WRITING THE PAYLOAD to the http call
        OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
        writer.write(payload);
        writer.close();

        //READING RESPONSE
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuffer jsonString = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            jsonString.append(line);
        }
        br.close();
        con.disconnect();

        return jsonString.toString();
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
    }
}
theLittleBox
  • 29
  • 1
  • 7
0

As discussed here the solution would be to change the content type to application/x-www-form-urlencoded, but since you are already using application/json; charset=UTF-8 (which I am assuming is a requirement of your project) you have no choise to redesign the whole thing. I suggest you one of the following:

If there are another solutions I'm not aware of, I don't know how much they would be compliant to HTTP protocol.

(More info)

Hope I helped!

Sterconium
  • 541
  • 4
  • 19
  • I think i will look more into whether i can change the content type or leave it out as mentioned and will return when i know more :) appreciate the help. – theLittleBox Sep 12 '19 at 09:57
  • i changed the content-type but unfortunately i still have problems defining the URL to begin with. I have gotten through to the API previosly with just localhost/scans and localhost/session, but as soon as there is a parameter i can't find the API call even though it is specified as in the top of my code. any clue as to how i would structure it?. – theLittleBox Sep 12 '19 at 10:25
  • I'm not too much experienced on the subject but I wouldn't exclude it is caused by bad set up of your application server and/or your project maven settings in such a way that only the url that works is actually published. I would check on that. – Sterconium Sep 12 '19 at 10:31
  • it is an external resource so how it is published is indeed a good question. but i am stuck with the issue of somehow getting the url accepted, whether a scan exist or not. but i really appreciate the help :) – theLittleBox Sep 12 '19 at 11:06
0

Why you are not using like this. Since you need to do a POST with HttpURLConnection, you need to write the parameters to the connection after you have opened the connection.

String urlParameters  = "scan_id=42324";
byte[] postData       = urlParameters.getBytes(StandardCharsets.UTF_8);

DataOutputStream dataOutputStream  = new DataOutputStream(conn.getOutputStream());
dataOutputStream.write(postData);

Or if you have launch in the end, just change the above code to the following,

String urlParameters  = "42324/launch";
byte[] postData       = urlParameters.getBytes(StandardCharsets.UTF_8);

DataOutputStream dataOutputStream  = new DataOutputStream(conn.getOutputStream());
dataOutputStream.write(postData);
Hasitha Jayawardana
  • 2,152
  • 3
  • 14
  • 32
  • considering i would do it like that, how would the original URI look like? - localhost/scans/launch, - localhost/scans//launch, - localhost/scans/?/launch, - localhost/scans/{scan_id}/launch, – theLittleBox Sep 12 '19 at 10:17
  • still fails somehow after adding the above code (tried both) and changing the url.. i am not sure what i am doing wrong as i just keep getting 400.. i can only suspect the URL since it worked with a POST on localhost/session but won't work on a localhost/scans ect. i want to add if i didn't make it clear before, that the url provided is localhost/scans/{scan_id}/launch where localhost is a replacement for the correct host as that is private. – theLittleBox Sep 12 '19 at 11:03
0
URL url = new URL("http://localhost/scans/{scan_id}/launch");

That line looks odd to me; it seems you are trying to use a URL where you are intending the behavior of a URI Template.

The exact syntax will depend on which template implementation you choose; an implementation using the Spring libraries might look like:

import org.springframework.web.util.UriTemplate;
import java.net.url;

// Warning - UNTESTED code ahead
UriTemplate template = new UriTemplate("http://localhost/scans/{scan_id}/launch");
Map<String,String> uriVariables = Collections.singletonMap("scan_id", "42324");
URI uri = template.expand(uriVariables);
URL url = uri.toURL();
VoiceOfUnreason
  • 40,245
  • 4
  • 34
  • 73
  • I tried implementing your example in spring by using the spring library and it tells me that i can't cast from UriTemplate to URL (the UriTemplate stems from the springframework). any further notes?. i am honestly going a bit downhill in the current implementation and was wondering if there is anything else you could recommend, still applicable in Java? It is important that i can add to the request headers and the payload. Any feedback is appreciated :) – theLittleBox Sep 12 '19 at 11:39
  • Example updated - I made a mistake in the transcription – VoiceOfUnreason Sep 12 '19 at 12:52