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.
Related
Trying to make a post call on one of our servers, but getting 400 BAD_REQUEST all the time
static void postUserToken()
{
final String url = "SERVER ADDRESS";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
MultiValueMap<String, String> requestBody= new LinkedMultiValueMap<>();
requestBody.add("userName", "TESTUSER");
requestBody.add("password", "TESTPASSWORD");
requestBody.add("auth", "secEnterprise");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class );
System.out.println(response);
}
get request to the same address works, post request via Postman works fine with the same body and headers
what am I missing ?
EDIT
calls from postman
POST /api/call/ HTTP/1.1
Host: SEREVERADDRESS:6405
Content-Type: application/json
Accept: application/json
User-Agent: PostmanRuntime/7.15.0
Cache-Control: no-cache
Postman-Token: token1,token2
Host: SEREVERADDRESS:6405
accept-encoding: gzip, deflate
content-length: 92
Connection: keep-alive
cache-control: no-cache
{
"password": "PASSWORD",
"auth": "secEnterprise",
"userName": "USER"
}
in response I get an object like this {"token":"longtoken"}
You are using a MultiValueMap however the json you send from postman looks like a simple Map.
This will produce {"key1":["val1"]} instead of {"key1":"val1"}
The problem might be in the
headers.setContentType(MediaType.APPLICATION_JSON);
Try using headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); or convert your data to a proper JSON.
More on this: https://www.baeldung.com/rest-template (4.4. Submit Form Data)
As far as I understand the problem and since I do not know your rest call details, I provide below the approach you can try.
Remove the following line.
requestBody.add("auth", "secEnterprise");
Add the line
headers.setHeader("auth", "secEnterprise");
If you are using other version of Apache Http Client, you can use the following code snippet.
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("header-name" , "header-value");
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.
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.
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)
I am developing a Restful Api. I am using laravel as backend (with apache) and for client I am using Android (with volley library for network communications).
In one of my call I have the following:
JsonArrayRequest jsonObjReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("Response", response.toString());
//PARSE JSON RESPONSE
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
for (Map.Entry<String, String> e: response.headers.entrySet()){
Log.d(e.getKey(), e.getValue());
}
return super.parseNetworkResponse(response);
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("Accept-Encoding","gzip,deflate");
return map;
}
};
As you can see I set Accept-Encoding :gzip,deflate.
When laravel receive the request, the headers exist:
array (
'accept-encoding' =>
array (
0 => 'gzip,deflate',
),
'host' =>
array (
0 => '192.168.1.104',
),
'connection' =>
array (
0 => 'Keep-Alive',
),
'user-agent' =>
array (
0 => 'Apache-HttpClient/UNAVAILABLE (java 1.5)',
),
'cookie' =>
array (
0 => 'laravel_session=,
),
'cookie2' =>
array (
0 => '$Version=1',
),
)
But when android receive the response it doesn't contains Content-Encoding : gzip header, the headers that it contains are:
Transfer-Encoding﹕ chunked
Date﹕ Sun, 21 Sep 2014 15:15:37 GMT
Keep-Alive﹕ timeout=5, max=99
Set-Cookie﹕ laravel_session=
Content-Type﹕ application/json
Connection﹕ Keep-Alive
X-Powered-By﹕ PHP/5.4.9-4ubuntu2.4
Server﹕ Apache/2.2.22 (Ubuntu)
Cache-Control﹕ no-cache
When I do the same request via curl:
curl -I -H 'Accept-Encoding: gzip' url
it return:
HTTP/1.1 200 OK
Date: Sun, 21 Sep 2014 14:46:12 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.4
Cache-Control: no-cache
Set-Cookie: laravel_session=
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
So, summarizing, I set Accept-Encoding:gzip,deflate, the request is receiveb by server with that headers but when response is received by android Content-Encoding doesn't exist. It is not problem of my server because curl works good.
Any suggestion? thanks
EDIT:
I am watching data sent and received using Wireshark between android and my server. I am watching other request a part from that. This other request is made with JsonObjectRequest instead of JsonArrayRequest and with wireshark I can watch the following headers.
Android -> Server
Content-Type: application/json\r\n
Host: 192.168.1.104\r\n
Connection: Keep-Alive\r\n
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.5)\r\n
[truncated] Cookie: laravel_session=
Cookie2: $Version=1\r\n
Accept-Encoding: gzip,deflate\r\n
Server -> android
Date: Sun, 21 Sep 2014 18:59:15 GMT\r\n
Server: Apache/2.2.22 (Ubuntu)\r\n
X-Powered-By: PHP/5.4.9-4ubuntu2.4\r\n
Cache-Control: no-cache\r\n
[truncated] Set-Cookie: laravel_session=
Vary: Accept-Encoding\r\n
Content-Encoding: gzip\r\n
Connection: Keep-Alive\r\n
Transfer-Encoding: chunked\r\n
Content-Type: text/html; charset=UTF-8\r\n
In this request the response contains Content-Encoding: gzip. The only different between this request and the other is that this request uses JsonObjectRequest instead JsonArrayRequest, so cant ´JsonArrayRequest use Gzip encode?