James W.
James W.

Reputation: 3055

java save http post requests hourly

I'm trying to set up a server on aws with simple http server and save each http post request headers & payload.

It works locally.

My steps after connection via ssh to the ec2 server:

It saves the headers to log file but not the payload and it doesn't returns 204 response.

Server.java

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;

public class Server {

    private static final int PORT = 80;
    private static final String FILE_PATH = "/home/ec2-user/logs/";
    private static final String UTF8 = "UTF-8";
    private static final String DELIMITER = "|||";
    private static final String LINE_BREAK = "\n";
    private static final String FILE_PREFIX = "dd_MM_YYYY_HH";
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FILE_PREFIX);
    private static final String FILE_TYPE = ".txt";

    public static void main(String[] args) {
        try {
            HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);
            server.createContext("/", new HttpHandler() {
                @Override
                public void handle(HttpExchange t) throws IOException {
                    System.out.println("Req\t" + t.getRemoteAddress());
                    InputStream initialStream = t.getRequestBody();
                    byte[] buffer = new byte[initialStream.available()];
                    initialStream.read(buffer);
                    File targetFile = new File(FILE_PATH + simpleDateFormat.format(new Date()) + FILE_TYPE);
                    OutputStream outStream = new FileOutputStream(targetFile, true);
                    String prefix = LINE_BREAK + t.getRequestHeaders().entrySet().toString() + LINE_BREAK + System.currentTimeMillis() + DELIMITER;
                    outStream.write(prefix.getBytes());
                    Map<String, String> queryPairs = new HashMap<>();
                    String params = new String(buffer);
                    String[] pairs = params.split("&");
                    for (String pair : pairs) {
                        int idx = pair.indexOf("=");
                        String key = pair.substring(0, idx);
                        String val = pair.substring(idx + 1);
                        String decodedKey = URLDecoder.decode(key, UTF8);
                        String decodeVal = URLDecoder.decode(val, UTF8);
                        queryPairs.put(decodedKey, decodeVal);
                    }
                    outStream.write(queryPairs.toString().getBytes());
                    t.sendResponseHeaders(204, -1);
                    t.close();
                }
            });
            server.setExecutor(Executors.newCachedThreadPool());
            server.start();
        } catch (Exception e) {
            System.out.println("Exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Upvotes: 0

Views: 106

Answers (1)

Jan
Jan

Reputation: 13858

Consider these changes to your handle method. As a starting point, two things are changed:

  • It reads the complete input and copies that into your file (initialStream.available() might not be the full truth)

  • catch, log and rethrow IOExceptions (you didn't see your 204 after all)

Consider redirecting your output into files, so you can check what happend on server later:

sudo nohup java Server > server.log 2> server.err &

If you described in more detail the desired target file structure we could figure something out there as well I guess.

            @Override
            public void handle(HttpExchange t) throws IOException {
                try {
                    System.out.println("Req\t" + t.getRemoteAddress());
                    InputStream initialStream = t.getRequestBody();
                    File targetFile = new File(FILE_PATH + simpleDateFormat.format(new Date()) + FILE_TYPE);
                    OutputStream outStream = new FileOutputStream(targetFile, true);
                    // This will copy ENTIRE input stream into your target file
                    IOUtils.copy(initialStream, outStream);
                    outStream.close();

                    t.sendResponseHeaders(204, -1);
                    t.close();
                } catch(IOException e) {
                    e.printStackTrace();
                    throw e;
                }
            }

Upvotes: 1

Related Questions