I'm trying to send a JSON as string (not as object) to the server (in this case it's a WebAPI). I always get a error code 500.
I succeeded to get response from the server when the request was GET and without sending data to the server. this achieved by JsonObjectRequest.
Now, I trying to send a POST request with JSON as string. For that I try
JsonObjectRequest
StringRequest
GsonRequest
JsonRequest - here I supplied my json in the requestBody
Before using volley, I used other methods to send request to server which require to simply build an object, serialized to json (string) and pass via StringEntity.
I can't understand where should I pass the json in the request. or what I'm doing wrong.
I don't exactly understand why do you want to send the JSON as a string and not as an object. Nevertheless, in your WebAPI endpoint you should put a breakpoint in the Post method of the ApiController and see whether the request gets there or not.
Probably, you're mixing the content-types of the request. If you want to send a simple string request from Volley, you should just use the StringRequest and send there the JSON text. Thus, in the WebAPI POST method you must get the string without being deserialized to JSON. I answered once a similar question of how this string request should be made here.
However, as I said before I would suggest using always JSON requests which includes the contentType:"application/json" header, and receive requests in the WebAPI deserialized.
url = "yoururl"; StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
Log.d("Response", response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", response);
}
} ) {
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("your_field", youJSONObject.toString());
return params;
} }; queue.add(postRequest);
Try in this way to make the post (it should work with json obj or array)
Related
I am writing a simple JSONArrayRequest. This is my JSONArrayRequest:
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
I'm confused on why we set the jsonRequest parameter in JsonArrayRequest to null. The only docs I found was this: https://developer.android.com/training/volley/request, which didn't really explain much. If somebody could explain this, I would really appreciate it. Thank you.
As the documentation says, the parameters of JsonArrayRequest are:
method - the HTTP method to use
url - URL to fetch the JSON from
jsonRequest - A JSONArray to post with the request. Null indicates no parameters will be posted along with request
listener - Listener to receive the JSON response
errorListener - Error listener, or null to ignore errors
So the null value you're passing is for the parameters to post along with the request, which can be null if you have nothing to pass.
jsonRequest as the name suggests json in request means something as payload you want to pass onto the server.
GET: is the type of HTTP method used for getting some info from the server and in that case we usually don't have to pass any payload to the server hence the jsonRequest is null in that case means the body will be empty in your API request.
POST/PUT: is the type of HTTP method used for creating/updating info on the server and in that case we have to pass any payload to server hence the jsonRequest is non-null in that case means the body will be the json data which we will pass as jsonRequest in your API request.
Update:
jsonRequest is of type JSONArray in JsonArrayRequest, so you can just convert your arraylist into jsonarray and pass it on.
ArrayList<String> list = new ArrayList<String>();
list.add("hello");
list.add("CodingChap");
JSONArray jsonArray = new JSONArray(list);
I am learning about Volley and I don't know why the response from GET method is coming as a single char -> [.
I am using this method to get the JSON response:
public void getJsonMethod() {
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
// String url = "https://www.w3schools.com/js/myTutorials.txt";
String url = "http://www.google.com"; // with this url I am getting response
// Request a string response from the provided URL.
final StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println("Response is: " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Response is not good" + error.getMessage());
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
When I am using this link I do get a response but when I try to use some link that contains nothing but JSON like this one my response it "[".
I am calling this method from Activity like this:
GetJsonClass getJson = new GetJsonClass(this);
getJson.getJsonMethod();
Any ideas on what am I doing wrong here?
Answer + code
If anyone will start using Volley maybe this can help him :
as David Lacroix said in his answer, I called stringRequest and notJsonArrayRequest.
Here is how it should have been:
public void getJsonMethod() {
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
String url = "your url";
JsonArrayRequest jsonObjectRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
System.out.println("this is response good" + response);
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("this is response bad" + error);
}
});
queue.add(jsonObjectRequest);
}
See https://developer.android.com/training/volley/request
StringRequest. Specify a URL and receive a raw string in response. See Setting Up a Request Queue for an example.
JsonObjectRequest and JsonArrayRequest (both subclasses of JsonRequest). Specify a URL and get a JSON object or array (respectively) in response.
You should be using a JsonArrayRequest
myTutorials.txt is being served with status code 304 (no proper suffix and MIME type either):
304 Not Modified. If the client has performed a conditional GET request and access is allowed, but the document has not been modified, the server SHOULD respond with this status code. The 304 response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields.
In other terms, what the browser may display is not neccessarily the same what the server has sent. eg. GSON would accept that JSON only with option lenient enabled, because the array has no name.
see RFC 2616.
I have teaching myself how to develop Android applications and I recently started using the Volley library for networking. I have been able to send basic requests with it. I was experimenting with Pocket's API to see if my app could fetch the items. Their documentation page mentions that I have to send a JSON request like so
POST /v3/oauth/request HTTP/1.1
Host: getpocket.com
Content-Type: application/json; charset=UTF-8
X-Accept: application/json
{"consumer_key":"1234-abcd1234abcd1234abcd1234",
"redirect_uri":"pocketapp1234:authorizationFinished"}
So I made a JSONObject in my app, added the key consumer_key with the value of my consumer key, then added in the key redirect_uri with its respective value. I sent this JSONObject as a request to the required URL as a POST request using Volley. The response code I received was 403, which is caused by a bad consumer key. I have double-checked the consumer key, so the problem lies with my request. How should I go about making the JSON request? Do I have to add the extra data, like Content-Type? If so, how?
If it is not too much, could you point me to a beginner-friendly resource on JSON, since I do not have much knowledge about web development?
Thank you.
What request methode do you use on your code? I am facing issue when using StringRequest method. Its work when use JsonObjectRequest method.
Here is how to create request besides on my experience.
Create Header Parameter
final Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("X-Accept", "application/json");
headers.put("consumer_key", "your-consumer-key");
headers.put("redirect_uri", "https://kamus.nusagates.com");
Create JSONObject From headers
JSONObject obj = new JSONObject(headers);
Create JsonObjectRequest
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("https://getpocket.com/v3/oauth/request", obj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//get all response data
Log.d("respon", String.valueOf(response));
try {
//get code from response
Log.d("respon code", response.getString("code"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
String server = String.valueOf(response.headers);
Log.d("header", server);
return super.parseNetworkResponse(response);
}
};
Add the request to The Queue
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
queue.add(jsonObjectRequest);
May this could help you solve your problem.
Cheers
Good evening,
Following this discussion, we are facing a new problem. We are trying to make a POST request (login) work on Android using the Volley library to make HTTP requests. The /login/ works well on Postman or Advanced REST Client, but it doesn't when using Volley. We have seen many other persons facing this problem and trying to find an answer on SO, but the only answer was to disable CSRF and we really don't want to do this.
On Postman, the response is 200 OK.
On Android Volley, the response is 403 forbidden : CSRF cookie not set.
Since we set CSRF_USE_SESSIONS as True, it doesn't make sense for us.
CSRF_USE_SESSIONS is True in Django
The library used to make HTTP requests on Android is Volley
We don't want to disable CSRF protection/middleware (I'm pointing this because many answers in other posts talking about this problem suggest to disable CSRF, but we are using it for both web client and mobile apps)
Here is the Java request :
private void loginPost(final String csrf) {
RequestQueue queue = Volley.newRequestQueue(getActivity());
String url = "https://api.ourapi.com/login/";
JSONObject object = new JSONObject();
try {
object.put("username", "hello");
object.put("password", "world");
System.out.println(object);
} catch (JSONException e) {
Log.d("Dude", "RIIIIIIIIIIIIIIIIIIIP");
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.POST, url, object, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// response
System.out.println("######################################");
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
System.out.println(error);
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Accept", "application/json");
params.put("X-CSRFToken", csrf);
System.out.println(params);
return params;
}
};
queue.add(jsonObjectRequest);
}
Here is the Django Login class-based view :
class Login(LoginView):
form_class = AuthenticationForm
template_name = 'users/login.html'
def post(self, request, *args, **kwargs):
if request.META.get('HTTP_ACCEPT') == 'application/json':
form = self.get_form()
if not form.is_valid():
print(form.errors.as_text())
return JsonResponse({'error': form.errors.as_text()}, status=400)
return super().post(request, *args, **kwargs)
We think that we are missing something in the Volley request headers or somewhere else. Can you guys help us ?
EDIT:
Here are our CSRF settings:
CSRF_COOKIE_AGE = None
CSRF_COOKIE_DOMAIN = '.ourapi.com'
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
CSRF_USE_SESSIONS = True
Self answer, here !
I kind of misunderstood how CSRF and session cookies work in Django. In the process_view function of the CsrfViewMiddleware, the reason message 403 forbidden - CSRF cookie not set is triggered when the CSRF token is None (see here). The csrf_token value comes from the _get_token(request) method from the same class, but it seems that the value returned is None (see here).
All we had to do was simply sending the session cookie to the server with the CSRF token in the header as X-CSRFToken !
I m using Volley library for sending a request to server for Login to an app. it doesn't have any problem until couple of hours ago. but without any reason, i m getting this error "BasicNetwork.performRequest: Unexpected response code 429"
the code is this:
public void loginRequest(final String username, final String password) {
String URL = Misc.Server_Url() + "login";
final StringRequest sr = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONObject obj;
try {
obj = new JSONObject(response);
if (obj.getInt("success") == 1) {
startActivity(new Intent(ActivityLogin.this, ActivityArticles.class));
finish();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("username", username.trim());
params.put("password", password);
return params;
}
};
RetryPolicy policy = new DefaultRetryPolicy(2 * 1000, 2, 2);
sr.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(sr);
}
I have searched in Wikipedia for this error (429) and i find that it means : "The user has sent too many requests in a given amount of time"
from server side(php) for more security if from an ip get more than for example 60 request within 10 second it will block that ip for a while... and client get 429 error code. i m wondering how it will occure when i send a single request to server same as above code!!! and in policy i set the try to 2 times Not more than that. i dont know why when i send this request i get error 429. means you have send 60 request within limited period of time.
do you know how to solve this problem?
thanks in advance...
Yes, as you said, the 429 response code states so. However, the tricky part is that the server sends this response code for either
You have sent too many requests in a short duration
The server has received too many requests by many others during that time
If you read the RFC related to the response code, you'll see that the RFC does not state that the server must identify individual users and only send them the busy status: 429. It could be because others are sending too many requests and the server is sending a 429 response to all.
In addition, the RFC states that the server should respond with a 429 response and the server MAY send the following parameter in its response header.
Retry-After: 3600
This would mean you should retry after this timeout.
the reason was coz of caching system in server.
if we send new request each time, it works fine. but if our request use from caching strategy system in server... it occur 429 error number...