I am trying to request data from an API.The requirements of the API are given below:
Base-URL for our API is https://api.openload.co/1 (note the 1 for
version 1 behind the /)
All requests to the API shall be HTTP/1.1 GET
Please make sure to use the API with https only.
Most requests require a API Login & API Key, you can find both in the
User Panel at the "User Settings" Tab. Response is json, structure is
as follows:
{ "status": <status-code>,
"msg": "<informational message. might vary, use the status code in your code!>",
"result": <result of the request. varies depending on the request>
}
I'm using the following method to get the json response:
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpsURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect()
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
But I'm recieveing the response code 403.
I'm using the below url to test it:
https://api.openload.co/1/account/info?login={login}&key={key}
When requesting from chrome, the response is obtained in form of a file.Could that be causing the issue as I'm expecting a json response String and the server is returning a file containing the json?
Could someone point out what I'm doing wrong as if I use the same url in chrome I'm getting the json response but can''t seem to get the response via code.
A response of 403 means you either submitted credentials improperly or you submitted invalid credentials. So, there seem to be two obvious places that could be causing your issue here.
Firstly, are you properly setting your login and key into the URL at the substitution points?
Secondly, are you sure you are a valid and active login and key?
Related
I am trying to get all the groups a user belongs to. When i run the below code i get 405 error. Am i not calling the resources correctly? Was following: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/users-operations#GetUsersMemberships
#RequestMapping(value="/groups", method = { RequestMethod.GET, RequestMethod.POST })
public JSONArray getMembersOf(HttpServletRequest httpRequest) {
try {
HttpSession session = httpRequest.getSession();
AuthenticationResult result =
(AuthenticationResult) session.getAttribute(AuthHelper.PRINCIPAL_SESSION_NAME);
String accessToken = result.getAccessToken();
String tenant = session.getServletContext().getInitParameter("tenant");
URL url =
new URL(String.format("https://graph.windows.net/%s/users/userId#abc.onmicrosoft.com/getMemberGroups?api-version=2013-04-05",
tenant, accessToken));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set the appropriate header fields in the request header.
conn.setRequestProperty("api-version", "2013-04-05");
conn.setRequestProperty("Authorization", accessToken);
conn.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
String goodRespStr = HttpClientHelper.getResponseStringFromConn(conn, true);
System.out.println("REsponse is --------------->>>>> "+goodRespStr);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Error:
java.io.IOException: Server returned HTTP response code: 405 for URL: https://graph.windows.net/abc.onmicrosoft.com/users/userId#abc.onmicrosoft.com/getMemberGroups?api-version=2013-04-05
According to your code, based on my understanding, I think you want to get collection that contains the object IDs of the groups of which the user is a member which is the Azure AD REST API Get Member Groups for Users. The error code returned from server seems to means Method Not Allowed which you can refer to the section 10.4.6 405 Method Not Allowed of HTTP RFC doc.
I think the issue might be caused by using an outdated value of api-version, please using 1.6 instread of 2013-04-05 in your code and try again.
Any update, please feel free to let me know.
I am trying to make my web service secure by making one of the methods require HTTP Basic authentication. In order to do this, I've implemented a custom Interceptor called LoginInterceptor that checks the requested URL, and if it corresponds to a method called open, it checks the message header for the username and password.
If there are no authentication fields in the header, the response code is set to HTTP_UNAUTHORIZED, and if the username or password is incorrect, the response code is set to HTTP_FORBIDDEN. Here's the code:
public LoginInterceptor() {
super(Phase.RECEIVE);
addAfter(RequestInterceptor.class.getName()); //another custom interceptor, for some simple redirections.
}
public void handleMessage(Message message) throws Fault {
String requestURI = message.get(Message.REQUEST_URI).toString();
String methodKeyword = requestURI.substring("localhost".length()+1).split("/")[0];
if(methodKeyword.equals("open")) {
AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
if(policy == null) {
sendErrorResponse(message, HttpURLConnection.HTTP_UNAUTHORIZED);
return;
}
//userPasswords is a hashmap of usernames and passwords.
String realPassword = userPasswords.get(policy.getUserName());
if (realPassword == null || !realPassword.equals(policy.getPassword())) {
sendErrorResponse(message, HttpURLConnection.HTTP_FORBIDDEN);
}
}
}
//This is where the response code is set, and this is where I'd like to write the response message.
private void sendErrorResponse(Message message, int responseCode) {
Message outMessage = getOutMessage(message);
outMessage.put(Message.RESPONSE_CODE, responseCode);
// Set the response headers
Map responseHeaders = (Map) message.get(Message.PROTOCOL_HEADERS);
if (responseHeaders != null) {
responseHeaders.put("Content-Type", Arrays.asList("text/html"));
responseHeaders.put("Content-Length", Arrays.asList(String.valueOf("0")));
}
message.getInterceptorChain().abort();
try {
getConduit(message).prepare(outMessage);
close(outMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
private Message getOutMessage(Message inMessage) {
Exchange exchange = inMessage.getExchange();
Message outMessage = exchange.getOutMessage();
if (outMessage == null) {
Endpoint endpoint = exchange.get(Endpoint.class);
outMessage = endpoint.getBinding().createMessage();
exchange.setOutMessage(outMessage);
}
outMessage.putAll(inMessage);
return outMessage;
}
//Not actually sure what this does. Copied from a tutorial online. Any explanation is welcome
private Conduit getConduit(Message inMessage) throws IOException {
Exchange exchange = inMessage.getExchange();
Conduit conduit = exchange.getDestination().getBackChannel(inMessage);
exchange.setConduit(conduit);
return conduit;
}
private void close(Message outMessage) throws IOException {
OutputStream os = outMessage.getContent(OutputStream.class);
os.flush();
os.close();
}
This works fine, however, I want to also return a message in the response, something like "incorrect username or password". I've tried, from within the sendErrorResponse method, doing:
outMessage.setContent(String.class, "incorrect username or password")
and I set the content-length to "incorrect username or password".length(). This doesn't work, I guess because the Apache CXF Messages use InputStreams and OutputStreams.
So I tried:
OutputStream os = outMessage.getContent(OutputStream.class);
try {
os.write("incorrect username or password".getBytes() );
outMessage.setContent(OutputStream.class, os);
} catch (IOException e) {
e.printStackTrace();
}
This doesn't work either. When stepping through with a debugger, I notice that os is null When testing with Postman, I get:
Could not get any response This seems to be like an error connecting
to http://localhost:9090/launcher/open. The response status was 0.
Check out the W3C XMLHttpRequest Level 2 spec for more details about
when this happens.
Pressing ctrl+shif+c (opening up dev tools) in Chrome, and checking the networks tab, I see:
"ERR_CONTENT_LENGTH_MISMATCH"
I've tried using an XMLStreamWriter, but that wans't any better.
Questions:
I can return the correct response code (401 Unauthorized and 403 forbidden), but how do I return a message in the response body?
Do I need to specifically extend a particular OutInterceptor like JASRXOutInterceptor in order to modify the message content?
I tried using a JAASInterceptor before, but I didn't manage to get that working. Could someone show me how to implement it that way, if that's somehow easier?
I could also just throw a fault like this: throw new Fault("incorrect username or password", Logger.getGlobal());, but then the HTTP response code would be 500. I'd prefer to return a proper 401 or 403 response.
Note:
Right now I'm still using HTTP for the transport layer. Once I fix this, I'll change to HTTPS.
Basically, what I wanted to do is return a fault with a HTTP response code of 401 (unauthorized) or 403 (forbidden) instead of 500 (server error). Turns out Apache CXF provides a simple way of doing that, using the Fault.setStatusCode(int) method, as I found from this question on Stack Overflow: how to throw a 403 error in Apache CXF - Java
So this is what my handleMessage method looks like now:
public void handleMessage(Message message) throws Fault {
String requestURI = message.get(Message.REQUEST_URI).toString();
String methodKeyword = requestURI.substring("localhost".length()+1).split("/")[0];
if(methodKeyword.equals("open")) {
AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
if(policy == null) {
Fault fault = new Fault("incorrect username or password", Logger.getGlobal());
fault.setStatusCode(401);
throw fault;
}
String realPassword = userPasswords.get(policy.getUserName());
if (realPassword == null || !realPassword.equals(policy.getPassword())) {
Fault fault = new Fault("incorrect username or password", Logger.getGlobal());
fault.setStatusCode(403);
throw fault;
}
}
}
I removed the other methods, they were unnecessary.
I am programming a jax-rs webservice which I want to contact from a java-program. I defined a #POST method which receives a String-array as input and is supposed to return a boolean value.
But really, how can i access this return value in java? I've been searching the web for several hours now, everybody writes example methods which return Strings or something else, but nobody shows how to access the returned value from another java program.
Here is the code from the program that contacts the #POST method:
ObjectOutputStream oos = null;
String[] login = {"XXXXXX","XXXXXXX"};
try {
login[1] = PasswordGenerator.hashPassword(login[1]);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url = new URL("XXXXX/XXXXXXX/XXXXXX/users/login/1");
try {
// creates a HTTP connection
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Boolean", "application/xml");
OutputStream outputStream = httpConn.getOutputStream();
oos = new ObjectOutputStream(outputStream);
outputStream.close();
System.out.println();
} finally {
if (oos != null) {
oos.close();
}
}
}
What I want to know is: What happens after I closed my outputStream? I mean, i started the POST method, but it is supposed to return a boolean value. Where is this value? How can I access it???
JAX-RS 2.0 has a Client API that provides you with a fluent API to retrieve the content of the response:
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://localhost:8080/xxx/")
.path("user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(login, MediaType.APPLICATION_XML) , Boolean.class);
But unfortunately, you'll need a custom MessageBodyWriter to convert the String[] into an XML document. Maybe you should change your server-side method (and client) to manipulate a DTO - a POJO with 2 fields, username and password - and annotated with #XmlRootElement ?
something like that:
(client-side)
Credentials credentials = new
credentials.setUsername("foo");
credentials.setUsername("hashedPwd");
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://xxxxx")
.path("/user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(credentials, MediaType.APPLICATION_XML) , Boolean.class);
System.out.println("Result: " + result);
(server-side)
#Path("/login/{id}")
#POST
public Boolean test(#PathParam("id") String login, Credentials credentials) {
...
}
I'm writing a Servlet in Java, that basically, gets a request with a XML in the Requests body, and then changes a few things in the XML and redirect/foreword the request with The new XML to a different Servlet that's on the same server, but its on a different web app.
How do redirect/foreword the request with The new XML? can i find code example any where?
this is what i have so far:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String body = getBody(request);
MapXml mapXml = new MapXml(body,
"C:\\Projects\\XmlMapper\\output.xml","C:\\Projects\\XmlMapper\\output\\");
String outputXml = mapXml.getOutputXml();
}
public static String getBody(HttpServletRequest request) throws IOException {
String body = null;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
return body;
}
And i have no idea how to continue on from here. I'm new to the servlet world.. Thanks!!! Cheers:)
If both web-apps are on the same server, i.e. Tomcat
in its META-INF/context.xml set <Context crossContext="true" />
getServletContext().getContext("/app").getRequestDispatcher("f.jsp").forward(..);,
where app is the name of the other application.
Or what you maybe should do is, Use URLConnection to send request to any URL.
URLConnection connection = new URL(url + "?" + query).openConnection();
connection.setRequestProperty("Accept-Charset", charset);
InputStream response = connection.getInputStream();
// ...
About how to set XML in request, you can carry relatively larger amounts of data in POST request. You can also find the max limit of POST data.
just read the bytes that make up the XML file (using FileInputStream)
(if you dont have xml in file, use String to create ur xml)and send
them in the POST body. Make sure to set the content encoding
accordingly.
I am editing this for the 4th time, to add more details.
You can use Apache HTTP Client to post XML easily if its difficult for you to use Java's HTTP client.
String xml = "your xml";
PostMethod post = new PostMethod(strURL);
try {
StringRequestEntity requestEntity = new StringRequestEntity(xml);
post.setRequestEntity(requestEntity); ..
....
...
Because the xml will not be a small body for request,so you have to let the client post the new xml for you. or you can do:
share the same database or cache with remote web service, and forward the key of the data in database or cache.
use HttpClient to post the request for your client, with modified xml, and return the response from remote service to your client.
if you can make sure the xml body is small, you can just using GET method, forward the request to remote server
Let's rule out some possibilities first:
You cannot do response.sendRedirect("/otherapp/servlet.do") since it doesn't let you send POST data to another webapp.
You cannot use session since you're sending data across to a different webapp.
You cannot obviously pass full XML in a query string using GET.
Once those possibilities are ruled out only possible way I can think of is this:
Return to the calling page with modified XML and URL of other webapps's servelt in response
Let calling page immediately POST the modified XML to other webapps's servelt using simple Javascript
I have an ASP.NET website that uses C# to create JSON via a WebMethod, the webmethod is then called from a Java android application via an http post. I provide the webmethod with a page id and it returns the page contents, in this case it returns the content for an error page.
This is the JSON returned by the webmethod:
D/WebInterface( 2353): {"d":[{"intId":2418,"strName":"Error 404","strTitle":"Ooo
ps, I couldn\u0027t find that!","strSummary":"Error 404, I couldn\u0027t find th
e page you\u0027re looking for.","strBody":"\u003cp\u003eYou could try browsing
the website or checking that you typed the URL correctly, if you came to this pa
ge from another site, please let me know and thanks for visiting.\u003c/p\u003e"
,"strUpdateDate":null,"strCreateDate":null}]}
I use Google GSON in my Android app to create an object from the JSON but it returns null no matter what I do. Here is my Google GSON method:
public static Containerdata resultsFromJson(String json)
{
try
{
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
Containerdata results = gson.fromJson(json, Containerdata.class);
Log.d("WebInterface", "RETURNING OBJECT FROM JSON");
return results;
}
catch(Exception e)
{
Log.d("WebInterface", "Error: Malformed JSON.");
return null;
}
}
This method returns Containerdata which is below:
public class Containerdata {
public List<Containerdata.Node> d;
public class Node
{
int intId;
String strName;
String strTitle;
String strSummary;
String strBody;
String strUpdateDate;
String strCreatedate;
}
}
Containerdata returned by resultsFromJson is always null no matter what I do to the json returned by the webmethod and I have no idea why. This is the method that gets my JSON from my WebMethod:
// Gets json in the form of a string from a web service
public static String dataFromWeb(String url, String postData)
{
Log.d("WebInterface", "Loading from web");
try
{
HttpURLConnection httpcon = (HttpURLConnection) ((new URL(url).openConnection()));
httpcon.setDoOutput(true);
httpcon.setRequestProperty("Content-Type", "application/json");
httpcon.setRequestProperty("Accept", "application/json");
httpcon.setRequestMethod("POST");
httpcon.connect();
byte[] outputBytes = postData.getBytes("UTF-8");
OutputStream os = httpcon.getOutputStream();
os.write(outputBytes);
os.close();
InputStream response = httpcon.getInputStream();
Log.d("WebInterface", Helpers.convertStreamToString(response));
return Helpers.convertStreamToString(response);
}
catch(Exception e)
{
Log.d("WebInterface", "failed from web... " + e.toString());
return "";
}
}
Could anyone please help and point me in the right direction, I'd be very greatful.
Thanks a lot in advance!
The problem is in the following code...
InputStream response = httpcon.getInputStream();
Log.d("WebInterface", Helpers.convertStreamToString(response));
return Helpers.convertStreamToString(response);
You're basically trying to read the InputStream twice. The first time is when you log the response and the second time is when you try to return the response. The problem is you can't read a stream when it has already been read (OK, you can but that requires different code).
If you want to log the response then read the string locally and then log it and return it...
InputStream response = httpcon.getInputStream();
String responseString = Helpers.convertStreamToString(response);
Log.d("WebInterface", responseString);
return responseString;