mirror of
https://github.com/skogaby/butterfly.git
synced 2026-04-25 16:06:52 -05:00
Another checkpoint commit, just fleshing out some of the boilerplate code for request handling
This commit is contained in:
parent
6494bbb50b
commit
4d504ce04e
|
|
@ -15,7 +15,6 @@ repositories {
|
|||
dependencies {
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
|
||||
compile group: 'commons-io', name: 'commons-io', version: '2.6'
|
||||
compile group: 'com.sparkjava', name: 'spark-core', version: '2.7.2'
|
||||
compile group: 'com.google.guava', name: 'guava', version: '23.5-jre'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
package com.buttongames.butterfly.http;
|
||||
|
||||
import com.buttongames.butterfly.compression.Lz77;
|
||||
import com.buttongames.butterfly.encryption.Rc4;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestMethodException;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestModelException;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestModuleException;
|
||||
import com.buttongames.butterfly.http.exception.MismatchedRequestUriException;
|
||||
import com.buttongames.butterfly.http.handlers.ServicesRequestHandler;
|
||||
import com.buttongames.butterfly.xml.BinaryXmlUtils;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import spark.Request;
|
||||
import spark.utils.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static spark.Spark.exception;
|
||||
import static spark.Spark.halt;
|
||||
|
|
@ -17,12 +25,34 @@ import static spark.Spark.threadPool;
|
|||
|
||||
/**
|
||||
* The main HTTP server. This class is responsible for the top-level handling of incoming
|
||||
* requests, then delegates the responsbility to the appropriate handler.
|
||||
* requests, then delegates the responsibility to the appropriate handler.
|
||||
* @author skogaby (skogabyskogaby@gmail.com)
|
||||
*/
|
||||
public class ButterflyHttpServer {
|
||||
|
||||
/**
|
||||
* Name of the HTTP header that contains the crypto key, if present.
|
||||
*/
|
||||
private static final String CRYPT_KEY_HEADER = "X-Eamuse-Info";
|
||||
|
||||
/**
|
||||
* Name of the HTTP header that says whether the packet is compressed.
|
||||
*/
|
||||
private static final String COMPRESSION_HEADER = "X-Compress";
|
||||
|
||||
/**
|
||||
* Value for the X-Compress header to indicate the packet is compressed.
|
||||
*/
|
||||
private static final String LZ77_COMPRESSION = "lz77";
|
||||
|
||||
/**
|
||||
* Static set of all the models this server supports.
|
||||
*/
|
||||
private static final ImmutableSet<String> SUPPORTED_MODELS;
|
||||
|
||||
/**
|
||||
* Static set of all the modules this server supports.
|
||||
*/
|
||||
private static final ImmutableSet<String> SUPPORTED_MODULES;
|
||||
|
||||
// Do a static setup of our supported models, modules, etc.
|
||||
|
|
@ -32,10 +62,16 @@ public class ButterflyHttpServer {
|
|||
SUPPORTED_MODULES = ImmutableSet.of("services");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ButterflyHttpServer() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the routes on our server and begins listening.
|
||||
*/
|
||||
public void startServer() {
|
||||
// configure the server properties
|
||||
int maxThreads = 20;
|
||||
|
|
@ -78,6 +114,8 @@ public class ButterflyHttpServer {
|
|||
((exception, request, response) -> halt(400, "Invalid request model.")));
|
||||
exception(InvalidRequestModuleException.class,
|
||||
((exception, request, response) -> halt(400, "Invalid request module.")));
|
||||
exception(MismatchedRequestUriException.class,
|
||||
(((exception, request, response) -> halt(400, "Request URI does not match request body"))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,29 +125,47 @@ public class ButterflyHttpServer {
|
|||
* @param request The request to validate and unpack
|
||||
* @return A string representing the plaintext version of the packet, in XML format.
|
||||
*/
|
||||
private String validateAndUnpackRequest(Request request) {
|
||||
private String validateAndUnpackRequest(Request request) throws GeneralSecurityException, IOException {
|
||||
final String requestUriModel = request.queryParams("model");
|
||||
final String requestUriModule = request.queryParams("module");
|
||||
final String requestUriMethod = request.queryParams("method");
|
||||
|
||||
// validate the model is supported
|
||||
// 1) validate the model is supported
|
||||
if (!SUPPORTED_MODELS.contains(requestUriModel)) {
|
||||
throw new InvalidRequestModelException();
|
||||
}
|
||||
|
||||
// validate the module is supported
|
||||
// 2) validate the module is supported
|
||||
if (!SUPPORTED_MODULES.contains(requestUriModule)) {
|
||||
throw new InvalidRequestModuleException();
|
||||
}
|
||||
|
||||
// validate that the request URI matches the request body
|
||||
// TODO: Implement
|
||||
if (false) {
|
||||
throw new MismatchedRequestUriException();
|
||||
// 3) validate that the request URI matches the request body;
|
||||
final String encryptionKey = request.headers(CRYPT_KEY_HEADER);
|
||||
final String compressionScheme = request.headers(COMPRESSION_HEADER);
|
||||
byte[] reqBody = request.bodyAsBytes();
|
||||
|
||||
// decrypt the request if it's encrypted
|
||||
if (!StringUtils.isBlank(encryptionKey)) {
|
||||
reqBody = Rc4.decrypt(reqBody, encryptionKey);
|
||||
}
|
||||
|
||||
// return the request body
|
||||
// decompress the request if it's compressed
|
||||
if (!StringUtils.isBlank(compressionScheme) &&
|
||||
compressionScheme.equals(LZ77_COMPRESSION)) {
|
||||
reqBody = Lz77.decompress(reqBody);
|
||||
}
|
||||
|
||||
// convert the body to plaintext XML if it's binary XML
|
||||
if (BinaryXmlUtils.isBinaryXML(reqBody)) {
|
||||
reqBody = BinaryXmlUtils.binaryToXml(reqBody);
|
||||
}
|
||||
|
||||
// read the request body into an XML document and check its properties
|
||||
// to verify it matches the request URI
|
||||
// TODO: Implement
|
||||
return "";
|
||||
|
||||
// 4) return the XML document
|
||||
return new String(reqBody, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.buttongames.butterfly.util;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
|
@ -51,7 +51,7 @@ public class CollectionUtils {
|
|||
* @throws IOException
|
||||
*/
|
||||
public static byte[] readInputStream(final InputStream is) throws IOException {
|
||||
return IOUtils.toByteArray(is);
|
||||
return ByteStreams.toByteArray(is);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.buttongames.butterfly.util.CollectionUtils;
|
|||
import java.io.DataOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Class to help translating between binary and plaintext XML. Right now it's a very dumb
|
||||
|
|
@ -16,6 +17,18 @@ import java.io.IOException;
|
|||
*/
|
||||
public class BinaryXmlUtils {
|
||||
|
||||
/**
|
||||
* First bytes of a plaintext XML response, so we know if an array needs to be converted
|
||||
* to/from binary XML.
|
||||
*/
|
||||
private static final byte[] XML_PREFIX = "<?xml".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
/**
|
||||
* Converts the input to plaintext XML from binary.
|
||||
* @param input
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static byte[] binaryToXml(final byte[] input) throws IOException {
|
||||
final String tmpPath = System.getProperty("user.home") + "\\tmpkbin";
|
||||
final DataOutputStream dos = new DataOutputStream(new FileOutputStream(tmpPath));
|
||||
|
|
@ -29,7 +42,31 @@ public class BinaryXmlUtils {
|
|||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the input to binary XML from plaintext XML.
|
||||
* @param input
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static byte[] xmlToBinary(final byte[] input) throws IOException {
|
||||
return binaryToXml(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Says whether or not the input is binary XML.
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBinaryXML(final byte[] input) {
|
||||
boolean isBinary = false;
|
||||
|
||||
for (int i = 0; i < XML_PREFIX.length; i++) {
|
||||
if (input[i] != XML_PREFIX[i]) {
|
||||
isBinary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isBinary;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user