How to make HTTP GET request in URL that has params appended by & using Retrofit in Android?
URL: http://api.com?name=remote&class=TV
Currently, i am using:
#GET("http://api.com?name={name}&class={class}")
Call<CustomType> get(
#Path(value = "name",encoded = false) String name,
#Path(value = "class",encoded = false) String class);
I am getting following error:
java.lang.IllegalArgumentException: URL query string "name={name}&class={class}"
must not have replace block.
For dynamic query parameters use #Query.
It's a standard GET request url. Just use #Query:
#GET("http://api.com")
Call<CustomType> get(
#Query("name") String name,
#Query("class") String classs);
It will access url:
http://api.com?name=remote&class=TV
Related
I'm using this AWS Object ApiRequest.
I've a url endpoint: url = "https://...com/songs"
NOT WORKING REQUEST(response 500):
ApiRequest request1 = new ApiRequest().withPath(url + "?userId=s123")
.withHttpMethod(HttpMethodName.GET);
WORKING REQUEST(response 200):
Map<String, String> mapParams = new HashMap<>();
mapParams.put("userId", "s123");
ApiRequest request1 = new ApiRequest().withPath(url)
.withHttpMethod(HttpMethodName.GET)
.withParameters(mapParams);
This is the ApiRequest object documentation:
https://docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/index.html?com/amazonaws/mobileconnectors/apigateway/ApiRequest.html
Why doesn't it work when using the userId in the query string(url) vs as a parameter? What is the difference between withParameters to query string?
Here userId is passed as a path variable
BASE_URL + "?userId=s123"
and Here userId is passed as a query parameter
mapParams.put("userId", "s123");
The path variable is not working because the API is designed to get params via query params not using path variables. They have mentioned function
withParameters(mapParams)
for accepting the params.
Url params and query parameters are different. The query params are within the URL. HTTP Headers are NOT part of the URL. They're part of the HTTP Message. Maybe this could help;
What is the difference between HTTP parameters and HTTP headers?
In my Xamarin android application I need to make an api call to openweathermap to get current weather data according to the user's current location.
Here is my query string code:
url = "api.openweathermap.org/data/2.5/weather?lat=" +
_currentLocation.Latitude +
"&lon=" +
_currentLocation.Longitude +
"&APPID=" + openWeatherAPIKey
+ "&units=imperial";
Now in the method FetchUrlAsync I send the web request and retrieve the response json. Below is the code of the method:
async Task<JsonValue> FetchUrlAsync(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new System.Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (System.IO.Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
Console.Out.WriteLine("Response: {0}", jsonDoc.ToString());
// Return the JSON document:
return jsonDoc;
}
}
}
I get a System.URIFormatException thrown on the first line of the method because the format of the uri is wrong. I checked other stack overflow questions and I think it might be because my url string does not start with a http:// or ftp. But I can't add http:// or ftp in front of the url string because that leads to an unrecognized server.
Any solution to this issue? Or does it not have to do with adding the http:// or ftp prefix?
I need to execute request via Retrofit :
url = http://ENDPOINT_URL/users/77?expand=followers,image,followees
Code :
#GET(ENDPOINT_URL+"users/{user_id}?expand=" WHAT NEED PRESENT HERE???)
void getUserInfo(#Path("user_id) int userId, String... expand)
For userId i use Path annotation, but how i can say to Retrofit, that I need to use array items separated via comma?
I'm writing an Android app, which is a client to my web application. I'm trying to use RoboSpice to perform network requests.
First of all I decided to test an API call to obtain an OAuth2 token. The following curl command can be called to obtain it from command line:
curl -X POST -d "grant_type=password&username=user&password=pass" http://testid:testsecret#localhost:8000/oauth2/token/
user and pass are the credentials for a registered user and testid and testsecret are the id and secret of a registered app in my web application. This call returns a JSON object with a token and other parameters.
I'm trying to do the same request using RoboSpice. Here's the code I wrote for the request:
public class OAuth2Request extends SpringAndroidSpiceRequest<String> {
private final String user;
private final String pass;
public OAuth2Request(String user, String pass) {
super(String.class);
setRestTemplate(new RestTemplate());
getRestTemplate().getMessageConverters().add(new StringHttpMessageConverter());
this.user = user;
this.pass = pass;
}
#Override
public String loadDataFromNetwork() throws RestClientException {
String client_id = "testid";
String client_secret = "testsecret";
HttpBasicAuthentication authHeader = new HttpBasicAuthentication(client_id, client_secret);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
requestHeaders.setUserAgent("AndroidNotesApp/1.0");
String data = String.format("grant_type=password&username=%s&password=%s", this.user, this.pass);
HttpEntity<String> requestEntity = new HttpEntity<>(data, requestHeaders);
String url = "http://10.0.2.2:8000/oauth2/token/";
return getRestTemplate().postForObject(url, requestEntity, String.class);
}
}
The SpiceManager in my activity is declared like:
protected SpiceManager spiceManager = new SpiceManager(JacksonSpringAndroidSpiceService.class);
and the request is made by the following lines:
OAuth2Request req = new OAuth2Request(user, pass);
spiceManager.execute(req, new OAuth2RequestListener());
user and pass are Strings, which get their values from EditText views.
But when I try to run this request, I get an exception 400 BAD REQUEST.
I set up logging in my django app to print the requests which come to /oauth2/token/, and I see, that POST parameters are empty in this request (I expect them to be the same as during the curl request, something like {'grant_type': 'password', 'password': 'pass', 'username': 'user'}).
Why are POST parameters empty in case of RoboSpice request? What am I doing wrong?
P.S. Just in case: the oauth2 authentication in my django web application is implemented using DjangoOAuthToolkit with DjangoRestFramework.
UPDATE: I decided to setup nginx proxy before my django web application to log the request body. The request body I get from the Android app is the following:
\x22grant_type=password&username=user&password=pass\x22
So the strange \x22 symbol is added in the beginning and in the end of the body (I believe it is a double-quote " symbol, but I'm not sure). Seems that these \x22 screw up POST parameter parsing in django. How can I get rid of these symbols?
I managed to solve my problem, so I'm posting an answer in case it helps someone.
SpringAndroidSpiceRequest by default tries to map a java object into JSON, so when I tried to send a String in request body, it wrapped it in double quotes to make it a JSON string. I don't need to send a request body as a JSON string, and in order to do that I need to define additional message converters.
Strangely, these lines in constructor don't seem to do anything
setRestTemplate(new RestTemplate());
getRestTemplate().getMessageConverters().add(new StringHttpMessageConverter());
When I used debugger, it showed just one message converter, MappingJacksonHttpMessageConverter. So I decided to add my own message converters in loadDataFromNetwork method.
I needed two message converters: FormHttpMessageConverter, which will process request and make a request POST body from MultiValueMap, and MappingJacksonHttpMessageConverter, which will process the JSON response into OAuth2Token POJO, which I also declared.
I believe, that for simple testing of REST API with client (POST plain strings and receive plain strings) it'll be better to choose another implementation for SpiceRequest other than SpringAndroidSpiceRequest, but I decided to stick with it, as it'll be easier to implement the complete client for my web application.
The complete code for OAuth2Request:
public class OAuth2Request extends SpringAndroidSpiceRequest<OAuth2Token> {
private final String user;
private final String pass;
public OAuth2Request(String user, String pass) {
super(OAuth2Token.class);
this.user = user;
this.pass = pass;
}
#Override
public OAuth2Token loadDataFromNetwork() throws RestClientException {
String client_id = "testid";
String client_secret = "testsecret";
HttpBasicAuthentication authHeader = new HttpBasicAuthentication(client_id, client_secret);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
requestHeaders.setUserAgent("AndroidNotesApp/1.0");
MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
data.add("grant_type", "password");
data.add("username", this.user);
data.add("password", this.pass);
HttpEntity<?> requestEntity = new HttpEntity<>(data, requestHeaders);
String url = "http://10.0.2.2:8000/oauth2/token/";
getRestTemplate().getMessageConverters().clear();
getRestTemplate().getMessageConverters().add(new FormHttpMessageConverter());
getRestTemplate().getMessageConverters().add(new MappingJacksonHttpMessageConverter());
return getRestTemplate().postForObject(url, requestEntity, OAuth2Token.class);
}
}
I have a method on the Server side which gives me information about an specific name registered in my database. I'm accessing it from my Android application.
The request to Server is done normally. What I'm trying to do is to pass parameter to the server depending on the name I want to get.
Here's my Server side method:
#RequestMapping("/android/played")
public ModelAndView getName(String name) {
System.out.println("Requested name: " + name);
........
}
Here's the Android request to it:
private Name getName() {
RestTemplate restTemplate = new RestTemplate();
// Add the String message converter
restTemplate.getMessageConverters().add(
new MappingJacksonHttpMessageConverter());
restTemplate.setRequestFactory(
new HttpComponentsClientHttpRequestFactory());
String url = BASE_URL + "/android/played.json";
String nome = "Testing";
Map<String, String> params = new HashMap<String, String>();
params.put("name", nome);
return restTemplate.getForObject(url, Name.class, params);
}
In the server side, I'm only getting:
Requested name: null
Is it possible to send parameters to my Server like this?
The rest template is expecting a variable "{name}" to be in there for it to replace.
What I think you're looking to do is build a URL with query parameters you have one of two options:
Use a UriComponentsBuilder and add the parameters by that
String url = BASE_URL + "/android/played.json?name={name}"
Option 1 is much more flexible though.
Option 2 is more direct if you just need to get this done.
Example as requested
// Assuming BASE_URL is just a host url like http://www.somehost.com/
URI targetUrl= UriComponentsBuilder.fromUriString(BASE_URL) // Build the base link
.path("/android/played.json") // Add path
.queryParam("name", nome) // Add one or more query params
.build() // Build the URL
.encode() // Encode any URI items that need to be encoded
.toUri(); // Convert to URI
return restTemplate.getForObject(targetUrl, Name.class);
Change
String url = BASE_URL + "/android/played.json";
to
String url = BASE_URL + "/android/played.json?name={name}";
because the map contains variables for the url only!