GWT RequestBuilder setHeader not working - java

I am trying to connect to an OAuth2 Server implementation using the following class (posting full for completeness):
import com.google.gwt.http.client.*;
import com.googlecode.gwt.crypto.bouncycastle.util.encoders.Base64;
import java.util.Map;
import java.util.function.Consumer;
public class HttpManager {
private static String toFormData(Map<String, String> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : data.entrySet())
sb.append("&")
.append(entry.getKey())
.append("=")
.append(entry.getValue());
sb.deleteCharAt(0);
return sb.toString();
}
public void postFormData(String url, Map<String, String> data, Consumer<Response> onSuccess, Consumer<Response> onFail) throws RequestException {
final String dataAsString = toFormData(data);
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
builder.setHeader("Accept", "application/x-www-form-urlencoded");
builder.setHeader("Authorization", "Basic " + Base64.encode(("appId" + ":" + "oauthSecret").getBytes()));
builder.sendRequest(dataAsString, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
if(response.getStatusCode() >= 400) {
onFail.accept(response);
} else {
onSuccess.accept(response);
}
}
#Override
public void onError(Request request, Throwable throwable) {
onFail.accept(null);
}
});
}
}
As you can see, I clearly append Content-Type, Accept and Authorization to the header. Further, I post along some data.
In reality though, the request looks like this:
OPTIONS /oauth/token HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://192.168.2.101:8888
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
Access-Control-Request-Headers: accept, authorization, content-type
Accept: */*
Referer: http://192.168.2.101:8888/demo.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
I wouldn't expect to see a request like this, given the above setup. What happened to my request headers? Also, there is no request body left, at all. And why is the request type Option? Can anybody shed some light?

This is due to the request being cross-origin, and what you're seeing is the preflight request in CORS parlance. It's the expected behavior, and the server has to authorize it with the appropriate response header.

Related

error response for the PUT request in android app

I'm developing an Android app that supposed to send PUT request to local server and when I try the same request using curl, I get success response, but from the Android app I get error with PUT request, here is the request for both from mobile app and curl, I listened to both requests on my PC using netcat
user#Laptop:~$ nc -l 192.168.1.104 55555
PUT /api/relay/0 HTTP/1.1
Host: 192.168.1.104:55555
User-Agent: curl/7.58.0
Accept: application/json
Content-Length: 31
Content-Type: application/x-www-form-urlencoded
apikey=2E5DE48567FB10F2&value=1
user#Laptop:~$ nc -l 192.168.1.104 55555
PUT /api/relay/0 HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; HRY-LX1MEB Build/HONORHRY-LX1MEB)
Host: 192.168.1.104:55555
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 31
apikey=2E5DE48567FB10F2&value=1
here is my android java request
public void jsonRequestVolley(int method, String url, String requestBody) {
RequestQueue queue = Volley.newRequestQueue(context);
JsonObjectRequest jsonRequest = new JsonObjectRequest(
method,
url,
requestBody,
successResponse(),
errorResponse()
)
{
/**
* Passing some request headers
* */
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
return headers;
}
};
queue.add(jsonRequest);
}
the working curl command is
curl -X PUT -H "Accept: application/json" http://192.168.1.105:55555/api/relay/0 --data "apikey=2E5DE48567FB10F2&value=1"```
I fixed the header because of local server requirements so, it worked now it look like
PUT /api/relay/0 HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; HRY-LX1MEB Build/HONORHRY-LX1MEB)
Host: 192.168.1.104:55555
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 31
I added the following to Android code
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
return headers;
}
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded";
}
all in request code.

NanoHttpd - return gzipped response

How can I enable GZIP compression in NanoHttpd?
Java code (starts web server and returns the same default response for any request):
package com.example;
import java.io.*;
import java.nio.charset.Charset;
import fi.iki.elonen.NanoHTTPD;
import static fi.iki.elonen.NanoHTTPD.Response.Status.OK;
public class App extends NanoHTTPD {
public App() throws IOException {
super(8080);
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
}
public static void main(String[] args) {
try {
new App();
} catch (IOException ioe) {
System.err.println("Couldn't start server:\n" + ioe);
}
}
#Override
public Response serve(IHTTPSession session) {
ByteArrayInputStream resBody = new ByteArrayInputStream(new byte[0]);
try {
resBody = new ByteArrayInputStream("{\"response\":1}".getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
}
Response res = newChunkedResponse(OK, "application/json", resBody);
res.setGzipEncoding(true);
return res;
}
}
And this request:
GET / HTTP/1.1
Host: localhost:8080
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ru;q=0.8
Produces this response:
HTTP/1.1 200 OK
Content-Type: application/json
Date: Tue, 28 Aug 2018 11:39:12 GMT
Connection: keep-alive
Transfer-Encoding: chunked
{"response":1}
Is there a way to enable GZIP for NanoHttpd responses?
Add something like this to your server:
protected boolean useGzipWhenAccepted(Response r) {
return true;
}
Also there's no need to use res.setGzipEncoding(true); as it's called automatically.
if the header doesn't contains {'Accept-Encoding':'gzip'} or not even 'Accept-Encoding' header,then NanoHTTPD will default set useGzipEncode as false.To overcome this, you can gzip the data externally and pass the byte[] to the response.
public class Server extends NanoHTTPD {
byte[] bArr;
public Server(int port) {
super(port);
}
#Override
public Response serve(IHTTPSession session) {
return newFixedLengthResponse(Response.Status.OK,"application/octect-stream",new ByteArrayInputStream(this.bArr),bArr.length);
}
public void compressWithGzip(byte[] bArr) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
GZIPOutputStream gzip = new GZIPOutputStream(bout);
gzip.write(bArr,0,bArr.length);
gzip.close();
setByteArray(bout.toByteArray());
bout.close();
} catch (IOException e) {
//TODO
}
}
public void setByteArray(byte[] byteArray) {
this.bArr = byteArray;
}
}

Can get response from browser, but 401 unauthorized from resttemplate

Can get from the response from Chrome, but when I want to get it with resttemplate it gives me 401 response.
I try to add the exact Content Types with rest template but it still gives the 401 error.
here is the request that i get it from Chrome :
GET URL HTTP/1.1
Host: host
Connection: keep-alive
Cache-Control: max-age=0
Authorization: Basic auth
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en,de;q=0.9,tr;q=0.8
and here is the code that i used in java to connect the service :
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML, MediaType.TEXT_HTML));
messageConverters.add(converter);
restTemplate.setMessageConverters(messageConverters);
HttpEntity<Map<String, String>> entity = new HttpEntity<>(params,createHeaders(username, password));
restTemplate.getForObject("URL",String.class, entity);
public static HttpHeaders createHeaders(String username, String password) {
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Authorization", authHeader);
return httpHeaders;
}
It appears to be a problem with encoding the authorization token generation.
If you are sure about the username and password is correct, the only possibility is that the method/encoding used to generate the token is different on the browser(or the UI application which is generating the token) and the implementation of your createHeaders() method.
Please refer to the below links for more details:
What encoding should I use for HTTP Basic Authentication?
https://github.com/request/request/issues/1334
Hope it'll help.

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!

Android Volley with GSON Success but return null values

I have a problem using Volley with GSON. There is no error/exception but the result returned by webservice is always null.
This is my webservice setting :
Status
200 OK Show explanation Loading time: 59
Request headers
CSP: active
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,id;q=0.6
Response headers
Date: Wed, 24 Jun 2015 02:37:06 GMT
Server: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.19
X-Powered-By: PHP/5.5.19
Content-Length: 81
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json; charset=utf-8
I'm sure the webservice is working fine, so the problem is in the Java code.
This is my custom request, taken from here :
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
Log.e("gson", "test");
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
Response result = Response.success(
gson.fromJson(json, gsonClass),
HttpHeaderParser.parseCacheHeaders(response));
return result;
} catch (UnsupportedEncodingException e) {
Log.e("gson", e.getLocalizedMessage()); //never printed
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
Log.e("gson", e.getLocalizedMessage()); //never printed
return Response.error(new ParseError(e));
}
}
And this is how i call the Volley, the Customer in onResponse is null :
RequestQueue queue = Volley.newRequestQueue(getActivity());
String url = "https://sister-8.tafinance.com/cust_gathering/index.php/customer/get/format/json";
final Map<String,String> header = new HashMap<String, String>();
//header.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
header.put("name", "test1");
header.put("born_date", "1970-06-15 00:00:00.000");
GsonRequest request = new GsonRequest(Request.Method.POST, url, Customer.class, header,
new Response.Listener<Customer>()
{
#Override
public void onResponse(Customer customer) {
txtTest.setText(customer.getName());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
txtTest.setText("" + volleyError.getMessage());
}
}
);
queue.add(request);
Please kindly help me. Thanks a lot for your help.
What kind of web server do you use? Usually underscore is not accepted for http header field name. (born_date (x), Born-Date(o)
Why underscores are forbidden in HTTP header names, https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Field_names)
You can also change settings of web server to accept underscore for http header field name.
(Refer to http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers)

Categories