-2

Is there a way I can send HTTP POST like this:
1.Send everything before header.
2.Do something...
3.Send the reset of the request(data)

I tried to use HTTPUrlConnection. But, I did not find a method like send() to explicitly send part of the HTTP request first.
Do I have to go down to Socket to build the request all by myself?

Adding more clarification:
Maybe the question is not clear enough.
So, we all know that HTTP is on top of socket connection. So, what I said is not changing the sequence of data sending via socket. But, I need the socket to send all data until headers, then hold, keep the connection. Another http request will be send to trigger an even on server side. Then finish sending all the data. Close the connection.

This is related to server side implementation. But, that is out of the topic of my question. So, please don't say the server should not design in that way.

As I already said, This can be done via building the HTTP request from socket. But, I want to see if there is anyway to achieve this without doing everything at socket level.

This can be done easily in python.

self._conn = httplib.HTTPConnection(ip, port, timeout=120)
self._conn.putrequest('POST', '/yourserveraddresss')
self._conn.putheader('format', 'InterleavedInt16')
self._conn.putheader('number-of-channels', '2')
self._conn.putheader('sample-rate', '16000')
self._conn.putheader('transfer-encoding', 'chunked')
self._conn.endheaders()

So, this will open the connection and send the headers. And the connection will be keep open. So, you can do something. and then:

self._conn.send(chunked_data)
self._conn.close()

So, in Java. If you useing HttpUrlConnection. Can you do that?
Or, maybe other util like Apache HttpClient?

user1947415
  • 933
  • 4
  • 14
  • 31
  • 2
    Sounds like an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Please describe what effect you want to achieve with this (and/or why you want to do it) - there may be other/better ways to achieve the result than what you have asked here. – Erwin Bolwidt Jan 23 '18 at 02:48
  • With your updated question - it does look like you'd want to use a socket connection - seems like you'd need one socket for the difficult part you're trying to accomplish and likely just a plain old HTTPUrlConnection for the second connection. The socket would do as you described, pausing the output while the HTTPUrlConnection performs it's job, then you unpause the socket and send the rest - its not really pausing per se, just an example - I'm thinking you're going to need some threading with a way to notify the original thread when the HTTPUrlConnection thread is finished – JGlass Jan 23 '18 at 18:43
  • Yes, the second connection doesn't matter. It doesn't necessarily to be a connection. You can just assume it's a sleep. And i don't need thread. I can just do something like this: socket.write(every bytes until/include all headers); – user1947415 Jan 23 '18 at 18:55
  • Yes, the second connection doesn't matter. It doesn't necessarily to be a connection. You can just assume it's a sleep. And i don't need thread. I can just do something like this: socket.write(every bytes until/include all headers); //do something socket.write(data); socket.write(""); @JGlass My question is can I do the difficult part with some higher level until similar to the one in python instead of socket. – user1947415 Jan 23 '18 at 19:01
  • It "looks" like you might be able to setAllowUserInteraction possibly, see this example where the persons pausing a download - might help! [Implement pause resume in file downloading](https://stackoverflow.com/questions/15349296/implement-pause-resume-in-file-downloading/15550013) – JGlass Jan 23 '18 at 19:31
  • I updated my answer based on (new information, new requests, clarifications)." – ronchi82 Jan 24 '18 at 00:44

3 Answers3

1

Not possible, you could only send the header at the begening of the request, otherwise will be interpreted as part of the message. Relevant: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

HTTP 1.1 is basically text over a connection, if you want to experiment open a socket in port 80 with the server and send text over the pipe, but all you get are probablly ERRO 400 Invalid Request.

Edit : For the sake of completation:

1- The client wich send headers and wait something before send data:

package requestholder;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;


public class RequestHolder {

    private static final DateFormat dateFormater= new SimpleDateFormat("yyyy-mm-aa hh:MM:ss");

    private static final String USER_AGENT = "Mozilla/5.0";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {

        URL url = new URL("http://localhost:8084/WebApplication2/Hold");

        HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();

        //no buffer, imediate flush
        httpConnection.setChunkedStreamingMode(1);

        //just in case....might matter for some servers
        httpConnection.setAllowUserInteraction(true);

        // Send post request
        httpConnection.setDoOutput(true);

        //add request headers
        httpConnection.setRequestMethod("POST");
        httpConnection.setRequestProperty("User-Agent", USER_AGENT);
        httpConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");



        StringBuilder someDataToSend = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            someDataToSend.append("word_:");
            someDataToSend.append(i);
            someDataToSend.append("  ");

        }

        DataOutputStream outPutWriter = new DataOutputStream(httpConnection.getOutputStream());

        //if ther's somenthing on the pipe (wich i doubt..), flush
        outPutWriter.flush();

        //************ represents slow logic here (Wait for other Thread/Connection), the headers has been sent and makes server wait for data
        Thread.sleep(20000);

        // send the remaing data
        outPutWriter.writeBytes(someDataToSend.toString());
        outPutWriter.flush();
        outPutWriter.close();

        //read the response from here
        int responseCode = httpConnection.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);

        System.out.println("Response Code : " + responseCode);

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

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

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

   }

2- A simple servlet to prove the concept:

package teste;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 */
@WebServlet(name = "Hold", urlPatterns = {"/Hold"})
public class Hold extends HttpServlet {

     private static final DateFormat format= new SimpleDateFormat("yyyy-mm-dd HH:MM:ss");
    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //print the headers
        Enumeration<String> headerNames = request.getHeaderNames();
        String header;
        while (headerNames.hasMoreElements()) {
            header = headerNames.nextElement();
            System.out.println(format.format(System.currentTimeMillis())+":"+  header + ":" + request.getHeader(header));
        }


        BufferedReader dataReader = request.getReader();
        /* low on porpuse, to generate more lines*/
        char data[] = new char[1500];
        while(dataReader.read(data)>-1){
            System.out.println(format.format(System.currentTimeMillis())+":"+ new String(data));
        }

        //write a standart response
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet Hold</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet Hold at " + request.getContextPath() + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

3- The client output:

run:

Sending 'POST' request to URL : http://localhost:8084/WebApplication2/Hold

Response Code : 200

Servlet Hold

Servlet Hold at /WebApplication2

4- Finnally the servlet output, there's a 18 seconds ( How accurate is Thread.sleep? ) between headers and data:

2018-24-23 22:01:02:user-agent:Mozilla/5.0

2018-24-23 22:01:02:accept-language:en-US,en;q=0.5

2018-24-23 22:01:02:host:localhost:8084

2018-24-23 22:01:02:accept:text/html, image/gif, image/jpeg, *; q=.2, /; q=.2

2018-24-23 22:01:02:connection:keep-alive

2018-24-23 22:01:02:content-type:application/x-www-form-urlencoded

2018-24-23 22:01:02:transfer-encoding:chunked

2018-24-23 22:01:18:word_:0 word_:1 word_:2 word_:3 word_:4 word_:5 word_:6 word_:7 word_:8 word_:9

Credits:

https://www.mkyong.com/java/java-https-client-httpsurlconnection-example/

Implement pause/resume in file downloading

NetBeans templates.

ronchi82
  • 138
  • 1
  • 5
  • I like your answer - but technically he never said what the HTTP server was so if he implemented his own he might be able to accomplish what he wants - but then again, whats the point of doing that ;-) – JGlass Jan 23 '18 at 14:38
  • Yes, the answer maybe just "Not possible". – user1947415 Jan 23 '18 at 18:31
  • But, I think you may not get my exact problem/question. I have update my question. @JGlass – user1947415 Jan 23 '18 at 18:32
  • Apache HttpAsyncClient may do what you need... It's posible to delay the Future response consumation as well the data streaming of the response ... Link to example page https://hc.apache.org/httpcomponents-asyncclient-4.1.x/examples.html . Something like that ? – ronchi82 Jan 23 '18 at 20:50
0

Looks like it's impossible to do it with HttpUrlConnection due to the high level encapsulation and less flexibility this util is given.

I end up using socket to construct the HTTP from scratch. That way you can pause at any point of the stream and resume later.

user1947415
  • 933
  • 4
  • 14
  • 31
-1

Your question is meaningless. The header comes first, by definition, and 'everything before header' therefore doesn't refer to anything.

I didn't find a method like send()

There isn't one. The request isn't sent until you do something that requires input, such as getting the response code, or the input stream, unless you are using fixed length or chunked transfer mode.

It isn't clear what the actual purpose is here. The server won't do anything until it has received the entire request, and if you fiddle around while sending it, it may time you out.

EDIT It now appears you aren't aware of the URL and HttpURLConnection classes, which already do everything you need. I suggest you look them up, and study the relevant parts of the Java Tutorial.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • @tkruse What part of 'your question is meaningless' and 'there isn't one' isn't an answer? – user207421 Jan 23 '18 at 16:07
  • So, I can hack it by calling conn.getResponseCode() after I setup all headers and catch the ResponseTimeoutException. But, I think it will also send the "" in socket to indicate the end of HTTP connection. Also, I think the connection is not available for further data via socket after that. – user1947415 Jan 23 '18 at 18:38
  • No, you can't hack it at all. Everything, headers and request body, will be sent before you retrieve the response code. I've already said that. I don't know what you mean by 'send the ""', or 'the end of HTTP connection'. If you mean the end of the request, it is signalled in various ways depending on the transfer mode. You still haven't stated why you think you need to do this. – user207421 Jan 24 '18 at 00:44