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
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 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");
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();
}
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;
}
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!