Skip to content

Commit

Permalink
Started work on the pluggable request-answering strategy. (reverted f…
Browse files Browse the repository at this point in the history
…rom commit 0f6271c)
  • Loading branch information
LordFokas committed Sep 26, 2016
1 parent 0f6271c commit c4474df
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 98 deletions.
Expand Up @@ -416,7 +416,7 @@ public void execute() throws IOException {
// TODO: long body_size = getBodySize();
// TODO: long pos_before_serve = this.inputStream.totalRead()
// (requires implementation for totalRead())
r = httpd.handle(this);
r = httpd.serve(this);
// TODO: this.inputStream.skip(body_size -
// (this.inputStream.totalRead() - pos_before_serve))

Expand Down
73 changes: 31 additions & 42 deletions core/src/main/java/org/nanohttpd/protocols/http/NanoHTTPD.java
Expand Up @@ -70,7 +70,6 @@
import org.nanohttpd.protocols.http.threading.IAsyncRunner;
import org.nanohttpd.util.IFactory;
import org.nanohttpd.util.IFactoryThrowing;
import org.nanohttpd.util.IHandler;

/**
* A simple, tiny, nicely embeddable HTTP server in Java
Expand Down Expand Up @@ -123,7 +122,7 @@
* See the separate "LICENSE.md" file for the distribution license (Modified BSD
* licence)
*/
public class NanoHTTPD {
public abstract class NanoHTTPD {

public static final String CONTENT_DISPOSITION_REGEX = "([ |\t]*Content-Disposition[ |\t]*:)(.*)";

Expand Down Expand Up @@ -328,11 +327,6 @@ public ServerSocket getMyServerSocket() {
}

private IFactoryThrowing<ServerSocket, IOException> serverSocketFactory = new DefaultServerSocketFactory();

/**
* The handler that will respond to HTTP requests.
*/
protected IHandler<IHTTPSession, Response> httpHandler;

private Thread myThread;

Expand Down Expand Up @@ -369,14 +363,6 @@ public NanoHTTPD(String hostname, int port) {
this.myPort = port;
setTempFileManagerFactory(new DefaultTempFileManagerFactory());
setAsyncRunner(new DefaultAsyncRunner());

// TODO: remove this when the deprecated serve() method is removed.
// This makes it so that overriding the serve() method still works although deprecated.
this.httpHandler = new IHandler<IHTTPSession, Response>() {
@Override public Response handle(IHTTPSession input) {
return NanoHTTPD.this.serve(input);
}
};
}

/**
Expand Down Expand Up @@ -518,30 +504,18 @@ public IFactory<ITempFileManager> getTempFileManagerFactory() {
public void makeSecure(SSLServerSocketFactory sslServerSocketFactory, String[] sslProtocols) {
this.serverSocketFactory = new SecureServerSocketFactory(sslServerSocketFactory, sslProtocols);
}

/**
* @param handler The new HTTP Request Handler. The passed object will receive and respond to requests
* like the <code>NanoHTTPD.serve(IHTTPSession)</code> method used to in past releases.
*/
public final void setHTTPHandler(IHandler<IHTTPSession, Response> handler){
this.httpHandler = handler;
}

/**
* <b>DO NOT</b> override this to customize the server.<br />
* Instead, set a new IHandler&lt;IHTTPSession, Response&gt;.
* <br />
* <br />
* This method accepts incoming requests, and as per v3.0.0 design
* will pass them through interceptors (if any) and / or the http
* handler until the request is answered.
* Override this to customize the server.
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
*
* @param session The HTTP session
* @param session
* The HTTP session
* @return HTTP response, see class Response for details
* @see NanoHTTPD#setHTTPHandler(IHandler)
* @author LordFokas
*/
public Response handle(final IHTTPSession session) {
public Response serve(IHTTPSession session) {
Map<String, String> files = new HashMap<String, String>();
Method method = session.getMethod();
if (Method.PUT.equals(method) || Method.POST.equals(method)) {
Expand All @@ -553,18 +527,33 @@ public Response handle(final IHTTPSession session) {
return Response.newFixedLengthResponse(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage());
}
}

return httpHandler.handle(session);

// TODO: This looks horribly flawed and should be fixed!
Map<String, String> parms = session.getParms();
parms.put(NanoHTTPD.QUERY_STRING_PARAMETER, session.getQueryParameterString());
return serve(session.getUri(), method, session.getHeaders(), parms, files);
}

/**
* @param session The incoming request.
* @return A response to the given request.
* @deprecated this method was replaced by <code>NanoHTTPD.setHTTPHandler(IHandler)</code>
* and will be removed in the future without any warnings.
* Override this to customize the server.
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
*
* @param uri
* Percent-decoded URI without parameters, for example
* "/index.cgi"
* @param method
* "GET", "POST" etc.
* @param parms
* Parsed, percent decoded parameters from URI and, in case of
* POST, data.
* @param headers
* Header entries, percent decoded
* @return HTTP response, see class Response for details
*/
@Deprecated
protected Response serve(IHTTPSession session) {
public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {
return Response.newFixedLengthResponse(Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Not Found");
}

Expand Down
Expand Up @@ -113,14 +113,17 @@ public String put(String key, String value) {
private boolean encodeAsGzip;

private boolean keepAlive;
private List<String> cookieHeaders;

private List<String> cookieHeaders;

/**
* Creates a fixed length response if totalBytes>=0, otherwise chunked.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Response(IStatus status, String mimeType, InputStream data, long totalBytes) {
@SuppressWarnings({
"rawtypes",
"unchecked"
})
protected Response(IStatus status, String mimeType, InputStream data, long totalBytes) {
this.status = status;
this.mimeType = mimeType;
if (data == null) {
Expand All @@ -143,23 +146,23 @@ public void close() throws IOException {
}

/**
* Adds a cookie header to the list.
* Should not be called manually, this is an internal utility.
* Adds a cookie header to the list. Should not be called manually, this is
* an internal utility.
*/
public void addCookieHeader(String cookie) {
cookieHeaders.add(cookie);
}

/**
* Should not be called manually.
* This is an internally utility for JUnit test purposes.
* Should not be called manually. This is an internally utility for JUnit
* test purposes.
*
* @return All unloaded cookie headers.
*/
public List<String> getCookieHeaders() {
return cookieHeaders;
return cookieHeaders;
}

/**
* Adds given line to the header.
*/
Expand Down Expand Up @@ -240,7 +243,7 @@ public void send(OutputStream outputStream) {
printHeader(pw, entry.getKey(), entry.getValue());
}
for (String cookieHeader : this.cookieHeaders) {
printHeader(pw, "Set-Cookie", cookieHeader);
printHeader(pw, "Set-Cookie", cookieHeader);
}
if (getHeader("connection") == null) {
printHeader(pw, "Connection", (this.keepAlive ? "keep-alive" : "close"));
Expand Down Expand Up @@ -363,9 +366,9 @@ public void setStatus(IStatus status) {
public static Response newChunkedResponse(IStatus status, String mimeType, InputStream data) {
return new Response(status, mimeType, data, -1);
}
public static Response newFixedLengthResponse(IStatus status, String mimeType, byte[] data){
return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(data), data.length);

public static Response newFixedLengthResponse(IStatus status, String mimeType, byte[] data) {
return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(data), data.length);
}

/**
Expand Down
Expand Up @@ -80,9 +80,9 @@ public void exec(ClientHandler clientHandler) {
this.running.add(clientHandler);
createThread(clientHandler).start();
}
protected Thread createThread(ClientHandler clientHandler){
Thread t = new Thread(clientHandler);

protected Thread createThread(ClientHandler clientHandler) {
Thread t = new Thread(clientHandler);
t.setDaemon(true);
t.setName("NanoHttpd Request Processor (#" + this.requestCount + ")");
return t;
Expand Down
17 changes: 0 additions & 17 deletions core/src/main/java/org/nanohttpd/util/IHandler.java

This file was deleted.

Expand Up @@ -98,7 +98,7 @@ public void testCookieSentBackToClient() throws Exception {
assertEquals("name", cookies.getCookies().get(0).getName());
assertEquals("value", cookies.getCookies().get(0).getValue());
}

@Test
public void testMultipleCookieSentBackToClient() throws Exception {
this.testServer.cookiesToSend.add(new Cookie("name0", "value0", 30));
Expand All @@ -108,7 +108,7 @@ public void testMultipleCookieSentBackToClient() throws Exception {
HttpGet httpget = new HttpGet("http://localhost:8192/");
ResponseHandler<String> responseHandler = new BasicResponseHandler();
this.httpclient.execute(httpget, responseHandler);

assertEquals(4, this.httpclient.getCookieStore().getCookies().size());
}

Expand Down Expand Up @@ -137,7 +137,7 @@ public void testServerReceivesCookiesSentFromClient() throws Exception {
assertEquals(1, this.testServer.cookiesReceived.size());
assertTrue(this.testServer.cookiesReceived.get(0).getHTTPHeader().contains("name=value"));
}

@Test
public void testServerReceivesMultipleCookiesSentFromClient() throws Exception {
Calendar calendar = Calendar.getInstance();
Expand Down
Expand Up @@ -55,8 +55,8 @@
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.nanohttpd.protocols.http.IHTTPSession;
import org.nanohttpd.protocols.http.NanoHTTPD;
import org.nanohttpd.protocols.http.request.Method;
import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;

Expand All @@ -74,10 +74,8 @@ public TestServer() {
}

@Override
public Response serve(IHTTPSession session) {
StringBuilder sb = new StringBuilder(String.valueOf(session.getMethod()) + ':' + this.response);
Map<String, String> parms = session.getParms();
String uri = session.getUri();
public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms, Map<String, String> files) {
StringBuilder sb = new StringBuilder(String.valueOf(method) + ':' + this.response);

if (parms.size() > 1) {
parms.remove("NanoHttpd.QUERY_STRING");
Expand Down
Expand Up @@ -77,10 +77,10 @@ public Response serve(IHTTPSession session) {
return Response.newFixedLengthResponse(response);
}

/*@Override // TODO: clean up
public Response serve(IHTTPSession session) {
@Override
public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {
throw new UnsupportedOperationException();
}*/
}
}

@Override
Expand Down
Expand Up @@ -143,7 +143,7 @@ protected boolean isWebsocketRequested(IHTTPSession session) {
protected abstract WebSocket openWebSocket(IHTTPSession handshake);

@Override
public Response handle(final IHTTPSession session) {
public Response serve(final IHTTPSession session) {
Map<String, String> headers = session.getHeaders();
if (isWebsocketRequested(session)) {
if (!NanoWSD.HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(NanoWSD.HEADER_WEBSOCKET_VERSION))) {
Expand Down Expand Up @@ -174,9 +174,8 @@ public Response handle(final IHTTPSession session) {
}
}

// This probably doesn't need to be overridable anymore since the pluggable strategy kicked in.
protected Response serveHttp(final IHTTPSession session) {
return super.httpHandler.handle(session);
return super.serve(session);
}

/**
Expand Down
Expand Up @@ -124,14 +124,14 @@ public void setUp() {
@Test
public void testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue() {
this.headers.put("connection", "keep-alive, Upgrade");
Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);

assertNotNull(handshakeResponse);
}

@Test
public void testHandshakeReturnsResponseWithExpectedHeaders() {
Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);

assertNotNull(handshakeResponse);

Expand All @@ -143,7 +143,7 @@ public void testHandshakeReturnsResponseWithExpectedHeaders() {
public void testMissingKeyReturnsErrorResponse() {
this.headers.remove("sec-websocket-key");

Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);

assertNotNull(handshakeResponse);
assertEquals(Status.BAD_REQUEST, handshakeResponse.getStatus());
Expand All @@ -152,22 +152,22 @@ public void testMissingKeyReturnsErrorResponse() {
@Test
public void testWrongConnectionHeaderReturnsNullResponse() {
this.headers.put("connection", "Junk");
Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE));
}

@Test
public void testWrongUpgradeHeaderReturnsNullResponse() {
this.headers.put("upgrade", "not a websocket");
Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);
assertNull(handshakeResponse.getHeader(NanoWSD.HEADER_UPGRADE));
}

@Test
public void testWrongWebsocketVersionReturnsErrorResponse() {
this.headers.put("sec-websocket-version", "12");

Response handshakeResponse = this.nanoWebSocketServer.handle(this.session);
Response handshakeResponse = this.nanoWebSocketServer.serve(this.session);

assertNotNull(handshakeResponse);
assertEquals(Status.BAD_REQUEST, handshakeResponse.getStatus());
Expand Down

0 comments on commit c4474df

Please sign in to comment.