38

I would like to generate POST request to a server which requires authentication. I tried to use the following method:

private synchronized String CreateNewProductPOST (String urlString, String encodedString, String title, String content, Double price, String tags) {

    String data = "product[title]=" + URLEncoder.encode(title) +
                "&product[content]=" + URLEncoder.encode(content) + 
                "&product[price]=" + URLEncoder.encode(price.toString()) +
                "&tags=" + tags;
    try {
        URL url = new URL(urlString);
        URLConnection conn;
        conn = url.openConnection();
        conn.setRequestProperty ("Authorization", "Basic " + encodedString);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(data);
        wr.flush(); 
        // Get the response 
        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
        String line; 
        while ((line = rd.readLine()) != null) { 
            // Process line... 
            } 
        wr.close(); 
        rd.close(); 
        return rd.toString();
    } catch (MalformedURLException e) {

        e.printStackTrace();
        return e.getMessage();
    }
    catch (IOException e) {

        e.printStackTrace();
        return e.getMessage();
    } 
}

but the server doesn't receive the authorization data. The line which is supposed to add authorization data is the following:

conn.setRequestProperty ("Authorization", "Basic " + encodedString);

and the line

BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

also throws an IOException.

Anyway I would be very thankful if anyone could suggest any fix of the logic above in order to enable authorization using POST with UrlConnection.

but obviously it doesn't work as it is supposed to although if the same logic is used for GET request everything works fine.

Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
Niko Gamulin
  • 66,025
  • 95
  • 221
  • 286

8 Answers8

50

A fine example found here. Powerlord got it right, below, for POST you need HttpURLConnection, instead.

Below is the code to do that,

    URL url = new URL(urlString);
    URLConnection conn = url.openConnection();
    conn.setDoOutput(true);
    conn.setRequestProperty ("Authorization", encodedCredentials);

    OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());

    writer.write(data);
    writer.flush();
    String line;
    BufferedReader reader = new BufferedReader(new 
                                     InputStreamReader(conn.getInputStream()));
    while ((line = reader.readLine()) != null) {
      System.out.println(line);
    }
    writer.close();
    reader.close();

Change URLConnection to HttpURLConnection, to make it POST request.

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");

Suggestion (...in comments):

You might need to set these properties too,

conn.setRequestProperty( "Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty( "Accept", "*/*" );
Community
  • 1
  • 1
Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
  • 2
    This is GET request which is not a problem. – Niko Gamulin Jan 08 '10 at 10:27
  • 3
    Not a big difference in terms of authorization. – Adeel Ansari Jan 08 '10 at 12:17
  • 4
    It is if you came here looking for how to do the post bit :( – David Newcomb Dec 14 '12 at 19:40
  • This answer is not correct: This Answer is: http://stackoverflow.com/a/2165000/787202 – Bob Mar 10 '14 at 14:24
  • @Stallman: Same as what it means in the original question. You'll find `encodedString` instead of `encodedCredential`, which means password, simply. – Adeel Ansari Jul 30 '14 at 06:51
  • The bit above did not work when I tried it. I had to add set the following on the connection: uc.setRequestProperty( "Content-type", "application/x-www-form-urlencoded" ); uc.setRequestProperty( "Accept", "\*/\*" ); – Ray Kiddy Sep 08 '15 at 19:19
  • `setDoOutput(true)` forces `UrlConnection` to POST... right? – Yousha Aleayoub Apr 18 '16 at 18:36
  • @YoushaAleayoub: Nope. – Adeel Ansari Jun 06 '16 at 04:26
  • @AdeelAnsari, No? so what is this: http://stackoverflow.com/questions/8587913/what-exactly-does-urlconnection-setdooutput-affect – Yousha Aleayoub Jun 17 '16 at 11:44
  • @YoushaAleayoub, It's just stating that it's used to request body, which is usually the case with POST -- and PUT, not just POST. So, we can't say it forces to POST, that's what it does in practice though; but taking it for granted would be wrong. The right thing to use is `httpUrlConn.setRequestMethod("POST")`. – Adeel Ansari Jun 20 '16 at 04:29
  • @AdeelAnsari, good point and thanks for reply... but what if we use `URLConnection`, not `HTTPURLConnection`? – Yousha Aleayoub Jun 20 '16 at 12:23
  • @YoushaAleayoub, Why stick with `URLConnection`, when you really want to POST. Beware, HEAD, GET, POST, PUT etc., all are HTTP's methods, or might also be of some other protocol; but general URL doesn't care. – Adeel Ansari Jun 21 '16 at 03:03
15

I don't see anywhere in the code where you specify that this is a POST request. Then again, you need a java.net.HttpURLConnection to do that.

In fact, I highly recommend using HttpURLConnection instead of URLConnection, with conn.setRequestMethod("POST"); and see if it still gives you problems.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • 1
    This is the correct answer. You can not make a post request with URLConnection. You must use HttpURLConnection. – Bob Mar 10 '14 at 14:22
6

To do oAuth authentication to external app (INSTAGRAM) Step 3 "get the token after receiving the code" Only code below worked for me

Worth to state also that it worked for me using some localhost URL with a callback servlet configured with name "callback in web.xml and callback URL registered: e.g. localhost:8084/MyAPP/docs/insta/callback

BUT after successfully completed authentication steps, using same external site "INSTAGRAM" to do GET of Tags or MEDIA to retrieve JSON data using initial method didn't work. Inside my servlet to do GET using url like e.g. api.instagram.com/v1/tags/MYTAG/media/recent?access_token=MY_TOKEN only method found HERE worked

Thanks to all contributors

        URL url = new URL(httpurl);
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("client_id", id);
        params.put("client_secret", secret);
        params.put("grant_type", "authorization_code");
        params.put("redirect_uri", redirect);
        params.put("code", code);  // your INSTAGRAM code received 
        Set set = params.entrySet();
        Iterator i = set.iterator();
        StringBuilder postData = new StringBuilder();
        for (Map.Entry<String, String> param : params.entrySet()) {
            if (postData.length() != 0) {
                postData.append('&');
            }
            postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
        }
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");

        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
        conn.setDoOutput(true);
        conn.getOutputStream().write(postDataBytes);
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        StringBuilder builder = new StringBuilder();
        for (String line = null; (line = reader.readLine()) != null;) {
            builder.append(line).append("\n");
        }
        reader.close();
        conn.disconnect();
        System.out.println("INSTAGRAM token returned: "+builder.toString());
lejallec
  • 61
  • 1
  • 2
2

To send a POST request call:

        connection.setDoOutput(true); // Triggers POST.

If you want to sent text in the request use:

        java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(connection.getOutputStream());
        wr.write(textToSend);
        wr.flush();
Dimitris
  • 3,975
  • 5
  • 25
  • 27
  • nope. `connection.setDoOutput(true);` **does not trigger** POST. Add this line `System.out.println(((HttpURLConnection)connection).getRequestMethod());` and you will read `GET`. – Würgspaß Aug 15 '18 at 12:28
1

I ran into this problem today and none of the solutions posted here worked. However, the code posted here worked for a POST request:

// HTTP POST request
private void sendPost() throws Exception {

    String url = "https://selfsolve.apple.com/wcResults.do";
    URL obj = new URL(url);
    HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

    //add reuqest header
    con.setRequestMethod("POST");
    con.setRequestProperty("User-Agent", USER_AGENT);
    con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

    String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";

    // Send post request
    con.setDoOutput(true);
    DataOutputStream wr = new DataOutputStream(con.getOutputStream());
    wr.writeBytes(urlParameters);
    wr.flush();
    wr.close();

    int responseCode = con.getResponseCode();
    System.out.println("\nSending 'POST' request to URL : " + url);
    System.out.println("Post parameters : " + urlParameters);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in = new BufferedReader(
            new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    //print result
    System.out.println(response.toString());

}

It turns out that it's not the authorization that's the problem. In my case, it was an encoding problem. The content-type I needed was application/json but from the Java documentation:

static String encode(String s, String enc)
Translates a string into application/x-www-form-urlencoded format using a specific encoding scheme.

The encode function translates the string into application/x-www-form-urlencoded.

Now if you don't set a Content-Type, you may get a 415 Unsupported Media Type error. If you set it to application/json or anything that's not application/x-www-form-urlencoded, you get an IOException. To solve this, simply avoid the encode method.

For this particular scenario, the following should work:

String data = "product[title]=" + title +
                "&product[content]=" + content + 
                "&product[price]=" + price.toString() +
                "&tags=" + tags;

Another small piece of information that might be helpful as to why the code breaks when creating the buffered reader is because the POST request actually only gets executed when conn.getInputStream() is called.

Harvinder
  • 274
  • 3
  • 15
1

On API 22 The Use Of BasicNamevalue Pair is depricated, instead use the HASMAP for that. To know more about the HasMap visit here more on hasmap developer.android

package com.yubraj.sample.datamanager;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import com.yubaraj.sample.utilities.GeneralUtilities;


import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

/**
 * Created by yubraj on 7/30/15.
 */
public class ServerRequestHandler {
    private static final String TAG = "Server Request";
    OnServerRequestComplete listener;

    public ServerRequestHandler (){

    }
    public void doServerRequest(HashMap<String, String> parameters, String url, int requestType, OnServerRequestComplete listener){

        debug("ServerRequest", "server request called, url  = " + url);
        if(listener != null){
            this.listener = listener;
        }
        try {
            new BackgroundDataSync(getPostDataString(parameters), url, requestType).execute();
            debug(TAG , " asnyc task called");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public void doServerRequest(HashMap<String, String> parameters, String url, int requestType){
        doServerRequest(parameters, url, requestType, null);
    }

    public interface OnServerRequestComplete{
        void onSucess(Bundle bundle);
        void onFailed(int status_code, String mesage, String url);
    }

    public void setOnServerRequestCompleteListener(OnServerRequestComplete listener){
        this.listener = listener;
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for(Map.Entry<String, String> entry : params.entrySet()){
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

    class BackgroundDataSync extends AsyncTask<String, Void , String>{
        String params;
        String mUrl;
        int request_type;

        public BackgroundDataSync(String params, String url, int request_type){
            this.mUrl = url;
            this.params = params;
            this.request_type = request_type;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... urls) {
            debug(TAG, "in Background, urls = " + urls.length);
            HttpURLConnection connection;
                debug(TAG, "in Background, url = " + mUrl);
                String response = "";
                switch (request_type) {
                    case 1:
                        try {
                            connection = iniitializeHTTPConnection(mUrl, "POST");
                            OutputStream os = connection.getOutputStream();
                            BufferedWriter writer = new BufferedWriter(
                                    new OutputStreamWriter(os, "UTF-8"));
                            writer.write(params);
                            writer.flush();
                            writer.close();
                            os.close();
                            int responseCode = connection.getResponseCode();
                            if (responseCode == HttpsURLConnection.HTTP_OK) {
                           /* String line;
                            BufferedReader br=new BufferedReader(new InputStreamReader(connection.getInputStream()));
                            while ((line=br.readLine()) != null) {
                                response+=line;
                            }*/
                                response = getDataFromInputStream(new InputStreamReader(connection.getInputStream()));
                            } else {
                                response = "";
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case 0:
                        connection = iniitializeHTTPConnection(mUrl, "GET");

                        try {
                            if (connection.getResponseCode() == connection.HTTP_OK) {
                                response = getDataFromInputStream(new InputStreamReader(connection.getInputStream()));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            response = "";
                        }
                        break;
                }
                return response;


        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if(TextUtils.isEmpty(s) || s.length() == 0){
                listener.onFailed(DbConstants.NOT_FOUND, "Data not found", mUrl);
            }
            else{
                Bundle bundle = new Bundle();
                bundle.putInt(DbConstants.STATUS_CODE, DbConstants.HTTP_OK);
                bundle.putString(DbConstants.RESPONSE, s);
                bundle.putString(DbConstants.URL, mUrl);
                listener.onSucess(bundle);
            }
            //System.out.println("Data Obtained = " + s);
        }

        private HttpURLConnection iniitializeHTTPConnection(String url, String requestType) {
            try {
                debug("ServerRequest", "url = " + url + "requestType = " + requestType);
                URL link = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) link.openConnection();
                conn.setRequestMethod(requestType);
                conn.setDoInput(true);
                conn.setDoOutput(true);
                return conn;
            }
            catch(Exception e){
                e.printStackTrace();
            }
            return null;
        }

    }
    private String getDataFromInputStream(InputStreamReader reader){
        String line;
        String response = "";
        try {

            BufferedReader br = new BufferedReader(reader);
            while ((line = br.readLine()) != null) {
                response += line;

                debug("ServerRequest", "response length = " + response.length());
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return response;
    }

    private void debug(String tag, String string) {
        Log.d(tag, string);
    }
}

and Just call the function when you needed to get the data from server either by post or get like this

HashMap<String, String>params = new HashMap<String, String>();
                    params.put("action", "request_sample");
                    params.put("name", uname);
                    params.put("message", umsg);
                    params.put("email", getEmailofUser());
                    params.put("type", "bio");
dq.doServerRequest(params, "your_url", DbConstants.METHOD_POST);
                    dq.setOnServerRequestCompleteListener(new ServerRequestHandler.OnServerRequestComplete() {
                        @Override
                        public void onSucess(Bundle bundle) {
                            debug("data", bundle.getString(DbConstants.RESPONSE));
                                                    }

                        @Override
                        public void onFailed(int status_code, String mesage, String url) {
                            debug("sample", mesage);

                        }
                    });

Now it is complete.Enjoy!!! Comment it if find any problem.

yubaraj poudel
  • 3,821
  • 1
  • 31
  • 28
0

HTTP authorization does not differ between GET and POST requests, so I would first assume that something else is wrong. Instead of setting the Authorization header directly, I would suggest using the java.net.Authorization class, but I am not sure if it solves your problem. Perhaps your server is somehow configured to require a different authorization scheme than "basic" for post requests?

jarnbjo
  • 33,923
  • 7
  • 70
  • 94
  • Nifty, I never knew about this class. However, this class is abstract, so he'd actually need an implementing class for it. – Powerlord Jan 29 '10 at 20:29
  • Sure, you need to implement an application specific way to get the credentials. In an interactive application, you may e.g. need a popup dialog. – jarnbjo Jan 29 '10 at 21:45
-1

i was looking information about how to do a POST request. I need to specify that mi request is a POST request because, i'm working with RESTful web services that only uses POST methods, and if the request isn't post, when i try to do the request i receive an HTTP error 405. I assure that my code isn't wrong doing the next: I create a method in my web service that is called through GET request and i point my application to consume that web service method and it works. My code is the next:

    URL server = null;
    URLConnection conexion = null;
    BufferedReader reader = null;
    server = new URL("http://localhost:8089/myApp/resources/webService");
    conexion = server.openConnection();
    reader = new BufferedReader(new InputStreamReader(server.openStream()));
    System.out.println(reader.readLine());
Oscar
  • 1