convert curl request into HttpURLConnection - java

I am trying to implement a client that logins first and do some staff.
This is my curl request:
curl -v https://api.example.com/api-token-auth/ \
-H "Accept: application/json" \
-d "username=myusername&password=mypassword"
I want to convert it into java code. Here is what I have tried:
HttpURLConnection conn;
URL obj = new URL("https://api.example.com/api-token-auth/");
URL obj = new URL(quoteURL);
conn = (HttpURLConnection) obj.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
String userpass = "username=myusername" + "&" + "password=mypassword";
String basicAuth = new String(Base64.getEncoder().encode(userpass.getBytes()));
conn.setRequestProperty("Authorization", basicAuth);
conn.setRequestProperty( "Accept", "*/*" );
conn.setRequestProperty( "Accept-Encoding", "gzip, deflate" );
conn.setRequestProperty( "Accept-Language", "en;q=1, fr;q=0.9, de;q=0.8,ja;q=0.7, nl;q=0.6, it;q=0.5" );
conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded; charset=utf-8" );
conn.setRequestProperty( "API-Version", "1.3.0" );
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty( "Accept", "*/*" );
conn.setRequestProperty("User-Agent", "Mozilla/5.0");
conn.connect();
InputStreamReader inputStreamReader = new InputStreamReader(conn.getInputStream());
BufferedReader in = new BufferedReader(inputStreamReader);
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
conn.disconnect();
return response;
Then I receive this error:
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: https://api.example.com/api-token-auth/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1839)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
I have tried several possible solutions, but no luck. I could nit find what I am doing wrong.

your curl request isn't actually doing HTTP basicAuth (which is what your example code is trying to do) - it's just POSTing the -d argument to the server (as a url encoded body)
so
get rid of all the setRequestProperty() stuff (it's not needed)
use con.setContentType("application/x-www-form-urlencoded") [which is arguably a bit cleaner]
write the userpass string to con.getOutputStream() [no need to base64 encode...again, this has nothing to do w/ http basicAuth]
for example, your curl command issues the following HTTP request
POST /api-token-auth/ HTTP/1.1
Host: api.example.com
User-Agent: curl/7.49.1
Accept: application/json
Content-Length: 39
Content-Type: application/x-www-form-urlencoded
username=myusername&password=mypassword
the following Java program would execute pretty much the EXACT same request
public class SO {
public static void main(String[] args) throws Exception {
String rsp = curl("http://axrsgpar0019:13080/api-token-auth/", "application/json", "username=myusername&password=mypassword");
}
public static String curl(String url, String accepts, String minusD) throws Exception {
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
con.setDoOutput(true);
con.setRequestProperty("Accept", accepts);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.getOutputStream().write(minusD.getBytes());
con.getOutputStream().close();
ByteArrayOutputStream rspBuff = new ByteArrayOutputStream();
InputStream rspStream = con.getInputStream();
int c;
while ((c = rspStream.read()) > 0) {
rspBuff.write(c);
}
rspStream.close();
return new String(rspBuff.toByteArray());
}
}
generates the following HTTP request (only difference is User-Agent and keep-alive..which should be insignificant)
POST /api-token-auth/ HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
User-Agent: Java/1.8.0_91
Host: api.example.com
Connection: keep-alive
Content-Length: 39
username=myusername&password=mypassword

Related

How to get access token from Spotify API? [java]

I am fairly new to programming with Java but am interested in creating a program that allows for connection to the Spotify API. I am using the Client Credential Flow authorization process but keep getting java.io.IOException: insufficient data written exception when trying to reach the access token. I cannot figure out what information I am missing to complete the request.
I found a YouTube video of the same process being completed in Python and they utilized the requests feature and .json() to receive the access token. Is there a similar way to complete this in Java?
try {
String str = "application/x-www-form-urlencoded";
byte[] hold = str.getBytes();
//create url
URL url = new URL(tokenURL);
//open connection to url
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
//setup post headers and body
conn.setRequestMethod("POST");
conn.setFixedLengthStreamingMode(32);
conn.setRequestProperty("Authorization",String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("grant_type", "client_credentials");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36");
//validate connection
int val = conn.getResponseCode();
String response = conn.getResponseMessage();
System.out.println("response code: " + val);
System.out.println("response: " + response);
}catch(Exception e){
System.out.println("error: " + e);
conn.disconnect();
}
PYTHON CODE
This code performs the action in python.
def spotifyAuth(clientID, clientSecret):
clientCred = f"{clientID}:{clientSecret}"
encodedClient = base64.b64encode(clientCred.encode())
tokenURL = "https://accounts.spotify.com/api/token"
method = "POST"
tokenData = {"grant_type" : "client_credentials"}
tokenHeader = {"Authorization" : f"Basic {encodedClient.decode()}"}
r = requests.post(tokenURL, data=tokenData, headers=tokenHeader)
tokenResponse = r.json()
accessToken = tokenResponse['access_token']
expires = tokenResponse['expires_in']
return accessToken, expires
Thanks to Rup I was able to identify the issue. I was not properly sending anything with the POST. I added .getOutputStream() so send the request and .getInputStream() to receive the response.
//create url access point
URL url = new URL(tokenURL);
//open http connection to url
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
//setup post function and request headers
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization",String.format("Basic %s", clientCredEncode));
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//set body for posting
String body = "grant_type=client_credentials";
//calculate and set content length
byte[] out = body.getBytes(StandardCharsets.UTF_8);
int length = out.length;
conn.setFixedLengthStreamingMode(length);
//connect to http
conn.connect();
//}
//send bytes to spotify
try(OutputStream os = conn.getOutputStream()) {
os.write(out);
}
//receive access token
InputStream result = conn.getInputStream();
s = new String(result.readAllBytes());
//System.out.println(s);
For anyone whos looking for the same, Here's a better one
import com.google.gson.JsonParser;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class SpotifyToken {
public String accessToken = "";
public String expiresIn = "";
public void get() throws IOException {
URL url = new URL(Endpoints.TOKEN);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setRequestProperty("content-type", "application/x-www-form-urlencoded");
String data = "grant_type=client_credentials&client_id=" + Endpoints.CLIENT_ID + "&client_secret=" + Endpoints.CLIENT_SECRET + "";
byte[] out = data.getBytes(StandardCharsets.UTF_8);
OutputStream stream = http.getOutputStream();
stream.write(out);
BufferedReader Lines = new BufferedReader(new InputStreamReader(http.getInputStream()));
String currentLine = Lines.readLine();
StringBuilder response = new StringBuilder();
while (currentLine != null) {
response.append(currentLine).append("\n");
currentLine = Lines.readLine();
}
this.accessToken = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("access_token"));
this.expiresIn = String.valueOf(JsonParser.parseString(String.valueOf(response)).getAsJsonObject().getAsJsonObject("expires_in"));
http.disconnect();
}
}
The class Endpoints.java will be
public class Endpoints {
public static final String CLIENT_ID = "YOUR_CLIENT_ID";
public static final String CLIENT_SECRET = "YOUR_CLIENT_SECRET";
public static final String TOKEN = "https://accounts.spotify.com/api/token";
}
If it interests you, here is the cURL command for the same:
curl --request POST \
--url 'https://accounts.spotify.com/api/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=YOUR_CLIENT_ID \
--data client_secret=YOUR_CLIENT_SECRET \
I used this tool to convert cURL to java code.

How to parse JSON response from an API url using https request in java?

how to parse the JSON response from an api url using java? When I run the below code
I am getting SocketTimeoutException. but when browse the URL in the Chrome and Microsoft Edge i am getting the JSON data.
url:"https://www.nseindia.com/api/quote-derivative?symbol=RELIANCE"
(use only for testing purpose. not for commercial use)
Java Code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
public class HTTP_Request {
public static void main(String[] args) {
try {
Send_HTTP_Request.call_me();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void call_me() throws Exception {
String url ="https://www.nseindia.com/api/quote-derivative?symbol=RELIANCE";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print in String
System.out.println(response.toString());
//Read JSON response and print
// JSONObject myResponse = new JSONObject(response.toString());
// System.out.println("result after Reading JSON Response");
// System.out.println("origin- "+myResponse.getString("origin"));
}
}
look what happens when you call the provided url from a shell curl:
> $ curl 'https://www.nseindia.com/api/quote-derivative?symbol=RELIANCE' [±master ●●▴]
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
You don't have permission to access "http://www.nseindia.com/api/quote-derivative?" on this server.<P>
Reference #18.15b5655f.1595338785.264b3809
</BODY>
</HTML>
So, I guess nseindia is blocking the request because is not coming from a browser.
But, if you try this:
curl 'https://www.nseindia.com/api/quote-derivative?symbol=RELIANCE' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'Cookie: ak_bmsc=D709927FAB6A44F1C243E20E9199ABA35F65B5158B040000E1EF165F44B95756~plIifDJa9J1EHznQiR/zQpjmGEFWOE88N83Yuqa0oOcgvvYh7eLlgD5MSFVhCZZOObVMZ7UDwEzmOQ2V2lJ6W9pPf6zEbQT1Je27i6h3hrAIyBYFMplV1EDo7rSLxXmCk+HGL3ynHmuPJsePDPD7WTljjTMnM1qpvixsCMEtM1BlmVmuXQijd8cKjWxLeLaf/cNAEJB6VC7SXOq+j6uj6oi9xF/Z2NYB905XnUg9YppXM=' -H 'Upgrade-Insecure-Requests: 1' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'
you get a json in the response.
{"info":{"symbol":"RELIANCE","companyName":"Reliance Industries Limited",.......}
So you need to add a couple of HTTP Headers to your request, something like:
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("Accept", "text/html");

Java https request get 403 response code for curseforge site

I try get redirect from https://www.curseforge.com/projects/291874 to https://www.curseforge.com/minecraft/mc-mods/serene-seasons but all tries response 403. I try HttpURLConnection, HttpsURLConnection and URLConnection but nothing to work.
How do request on this site?
Browser do this two steps:
CONNECT www.curseforge.com:443 HTTP/1.1
GET /projects/291874 HTTP/1.1
How do this on java?
Please check your code before answer (first link in question)
String url = "https://www.curseforge.com/projects/291874";
try {
HttpURLConnection con1 = (HttpURLConnection)(new URL(url).openConnection());
con1.setRequestProperty("Host", "www.curseforge.com");
con1.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:69.0) Gecko/20100101 Firefox/69.0");
con1.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
con1.setRequestProperty("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
con1.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
con1.setRequestProperty("DNT", "1");
con1.setRequestProperty("Connection", "keep-alive");
con1.setRequestProperty("Upgrade-Insecure-Requests", "1");
con1.connect();
//con1.getInputStream();
System.out.println(con1.getResponseCode());
System.out.println(con1.getHeaderField("Location"));
} catch (IOException e) {
e.printStackTrace();
}

Java USES HTTP v1 to send Chinese notifications that are error characters

The request header is the same as the official document. Why did android receive the wrong character when I used Chinese? Using English is correct
private HttpURLConnection getConnections() throws IOException {
URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getAccessTokens());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;
}

https post fails while http post succeeds with almost same code snippet in java?

There's a server supports both http and https service. I want to set an access password via java. The problem I met is I managed to do this with http but failed with https. I use the same code except different protocols. Below is my code for setting password:
//url = new URL("http://172.20.1.80/password");
//HttpURLConnection connection = setHttpConnect((HttpURLConnection) url.openConnection());
url = new URL("https://172.20.1.80/password");
HttpsURLConnection connection = setHttpsConnect((HttpsURLConnection) url.openConnection());
sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new MyTrust() }, new java.security.SecureRandom());
connection.setSSLSocketFactory(sc.getSocketFactory());
connection.setDoInput(true);
connection.setDoOutput(true);
StringBuffer set = new StringBuffer();
newpw = "123456";
boundary = "----abc123abc1234-java";
set.append(boundary + "\r\n").append("Content-Disposition: form-data; name=\"pw\"\r\n\r\n")
.append(newpw).append("\r\n" + boundary + "--\r\n")
.append("Content-Disposition: form-data; name=\"con_pw\"\r\n\r\n").append(newpw)
.append("\r\n" + boundary + "--\r\n");
out = new PrintWriter(connection.getOutputStream());
out.write(set.toString());
out.flush();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
while ((str = in.readLine()) != null) {
result += (str + "\n");
if (str.indexOf(pwSet) != -1) {
succ += 1;
setPwSucc = true;
}
}
This is the connection attributes:
private static HttpsURLConnection setHttpsConnect(HttpsURLConnection c) {
c.setRequestProperty("User-Agent", "java");
c.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
c.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
c.setRequestProperty("Accept-Encoding", "gzip, deflate");
c.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
c.setConnectTimeout(timeout); // timeout
c.setReadTimeout(timeout);
return c;
}
private static HttpURLConnection setHttpConnect(HttpURLConnection c) {
c.setRequestProperty("User-Agent", "sxf");
c.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
c.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
c.setRequestProperty("Accept-Encoding", "gzip, deflate");
c.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
c.setConnectTimeout(timeout); // timeout
c.setReadTimeout(timeout);
return (HttpURLConnection) c;
}
Setting for X509:
public class MyTrust implements X509TrustManager{
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {return null; }
}
The server can print some logs by webpage, and here are the log seperately:
//Log when https in use:
Length of RcvBuf: 336
This is RcvBuf:
POST /password HTTP/1.1 User-Agent: java Accept: text/html,application/xhtml+xml,app
lication/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding
: gzip, deflate Content-Type: multipart/form-data; boundary=----abc123abc1234-java Host: 172.20.1
.80 Connection: keep-alive Content-Length: 203
//Log when http in use:
Length of RcvBuf: 520
This is RcvBuf:
POST /password HTTP/1.1 User-Agent: sxf Accept: text/html,application/xhtml+xml,appl
ication/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding:
gzip, deflate Content-Type: multipart/form-data; boundary=----abc123abc1234-java Host: 172.20.1.
80 Connection: keep-alive Content-Length: 203 ----abc123abc1234-java Content-Disposition: for
m-data; name="pd" 123456 ----abc123abc1234-java-- Content-Disposition: form-data; n
ame="conpw" 123456 ----abc123abc1234-java--
It seems when HTTPS is in use, my data is not accepted by server.
But one thing confuse me more: there's another operation on the server, and before it is executed, password will be checked. With another code with correct password(the password is set via chrome then), I can execute this operation. Please comment if the code is helpful to analysize the problem.
Can anyone help me to make the https work? My 2nd question is, since I get nothing by the log printed in web page, what is the 203 in Content-Length: 203?
Thank you all in advance!

Categories