Fixed up multipart stuff, added proper js.
This commit is contained in:
		
							parent
							
								
									401859fa74
								
							
						
					
					
						commit
						df8a6dd192
					
				| 
						 | 
				
			
			@ -15,3 +15,4 @@ create-schematic-gen-site-test-*
 | 
			
		|||
*.obj
 | 
			
		||||
*.lst
 | 
			
		||||
*.jar
 | 
			
		||||
extracts/
 | 
			
		||||
							
								
								
									
										2
									
								
								dub.json
								
								
								
								
							
							
						
						
									
										2
									
								
								dub.json
								
								
								
								
							| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
	],
 | 
			
		||||
	"copyright": "Copyright © 2023, Andrew Lalis",
 | 
			
		||||
	"dependencies": {
 | 
			
		||||
		"handy-httpd": "~>7.6.1",
 | 
			
		||||
		"handy-httpd": "~>7.6.3",
 | 
			
		||||
		"slf4d": "~>2.4.1"
 | 
			
		||||
	},
 | 
			
		||||
	"description": "HTTP server for generating schematic materials lists.",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
	"fileVersion": 1,
 | 
			
		||||
	"versions": {
 | 
			
		||||
		"handy-httpd": "7.6.1",
 | 
			
		||||
		"handy-httpd": "7.6.3",
 | 
			
		||||
		"httparsed": "1.2.1",
 | 
			
		||||
		"slf4d": "2.4.1",
 | 
			
		||||
		"streams": "3.5.0"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
const form = document.getElementById("schematic-form");
 | 
			
		||||
const resultContainer = document.getElementById("result-container");
 | 
			
		||||
form.onsubmit = async (e) => {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    resultContainer.innerHTML = "";
 | 
			
		||||
    console.log(e);
 | 
			
		||||
    const data = new FormData(form);
 | 
			
		||||
    console.log(data);
 | 
			
		||||
| 
						 | 
				
			
			@ -10,9 +12,12 @@ form.onsubmit = async (e) => {
 | 
			
		|||
            body: data
 | 
			
		||||
        });
 | 
			
		||||
        const result = await response.json();
 | 
			
		||||
        console.log("Success:", result);
 | 
			
		||||
        const extractId = result.extractId;
 | 
			
		||||
        const url = window.location.origin + "/extracts/" + extractId;
 | 
			
		||||
        resultContainer.innerHTML = `<p>Copy this URL, and provide it to the computer: <em>${url}</em></p>`;
 | 
			
		||||
        form.reset();
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.error("Error: " + error);
 | 
			
		||||
        resultContainer.innerHTML = `<p>An error occurred: ${error}</p>`;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,9 @@
 | 
			
		|||
        <input id="schematic-file-input" name="schematics" type="file" multiple accept=".nbt" required/>
 | 
			
		||||
        <button type="submit">Submit</button>
 | 
			
		||||
    </form>
 | 
			
		||||
    <div id="result-container">
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    <script src="files.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										49
									
								
								source/app.d
								
								
								
								
							
							
						
						
									
										49
									
								
								source/app.d
								
								
								
								
							| 
						 | 
				
			
			@ -3,6 +3,12 @@ import handy_httpd.handlers.path_delegating_handler;
 | 
			
		|||
import handy_httpd.handlers.file_resolving_handler;
 | 
			
		||||
import slf4d;
 | 
			
		||||
import slf4d.default_provider;
 | 
			
		||||
import std.path;
 | 
			
		||||
import std.file;
 | 
			
		||||
 | 
			
		||||
const EXTRACTS_DIR = "extracts";
 | 
			
		||||
const EXTRACT_FILENAME = "__EXTRACT__.json";
 | 
			
		||||
const EXTRACT_COMMAND = ["java", "-jar", "materials-extractor-v1.0.0.jar"];
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
	auto provider = new shared DefaultProvider(true, Levels.INFO);
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +21,7 @@ void main() {
 | 
			
		|||
 | 
			
		||||
	PathDelegatingHandler handler = new PathDelegatingHandler();
 | 
			
		||||
	handler.addMapping("POST", "/extracts", &handleExtract);
 | 
			
		||||
	handler.addMapping("GET", "/extracts/{extractId:uint}", &getExtract);
 | 
			
		||||
	handler.addMapping("GET", "/extracts/{extractId}", &getExtract);
 | 
			
		||||
 | 
			
		||||
	FileResolvingHandler fileHandler = new FileResolvingHandler("site", DirectoryResolutionStrategies.serveIndexFiles);
 | 
			
		||||
	handler.addMapping("/**", fileHandler);
 | 
			
		||||
| 
						 | 
				
			
			@ -23,15 +29,46 @@ void main() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void handleExtract(ref HttpRequestContext ctx) {
 | 
			
		||||
	MultipartFormData data = ctx.request.readBodyAsMultipartFormData();
 | 
			
		||||
	infoF!"Read %d files: "(data.elements.length);
 | 
			
		||||
 | 
			
		||||
	import std.json;
 | 
			
		||||
	import std.uuid;
 | 
			
		||||
	import std.process;
 | 
			
		||||
	import std.stdio;
 | 
			
		||||
 | 
			
		||||
	immutable UUID extractId = randomUUID();
 | 
			
		||||
	MultipartFormData data = ctx.request.readBodyAsMultipartFormData();
 | 
			
		||||
	// TODO: Validate data (unique filenames, no non-file elements, etc.)
 | 
			
		||||
	const extractDir = buildPath(EXTRACTS_DIR, extractId.toString());
 | 
			
		||||
	if (!exists(extractDir)) {
 | 
			
		||||
		mkdirRecurse(extractDir);
 | 
			
		||||
	}
 | 
			
		||||
	string[] filenames;
 | 
			
		||||
	foreach (MultipartElement element; data.elements) {
 | 
			
		||||
		if (element.filename.isNull) continue;
 | 
			
		||||
		const filePath = buildPath(extractDir, element.filename.get());
 | 
			
		||||
		std.file.write(filePath, element.content);
 | 
			
		||||
		filenames ~= filePath;
 | 
			
		||||
	}
 | 
			
		||||
	const extractJsonPath = buildPath(extractDir, EXTRACT_FILENAME);
 | 
			
		||||
	infoF!"Running extract process on files: %s"(filenames);
 | 
			
		||||
	Pid pid = spawnProcess(EXTRACT_COMMAND ~ filenames, std.stdio.stdin, File(extractJsonPath, "w"));
 | 
			
		||||
	int exitCode = wait(pid);
 | 
			
		||||
	infoF!"Exit code: %d"(exitCode);
 | 
			
		||||
	if (exitCode != 0) {
 | 
			
		||||
		ctx.response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
 | 
			
		||||
		ctx.response.writeBodyString(readText(extractJsonPath));
 | 
			
		||||
	} else {
 | 
			
		||||
		JSONValue result = JSONValue.emptyObject;
 | 
			
		||||
	result.object["extractId"] = JSONValue(42);
 | 
			
		||||
		result.object["extractId"] = JSONValue(extractId.toString());
 | 
			
		||||
		ctx.response.writeBodyString(result.toJSON(), "application/json");
 | 
			
		||||
		// Remove schematic files after we are done.
 | 
			
		||||
		foreach (string schematicFile; filenames) {
 | 
			
		||||
			std.file.remove(schematicFile);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void getExtract(ref HttpRequestContext ctx) {
 | 
			
		||||
	infoF!"Getting extract: %d"(ctx.request.getPathParamAs!uint("extractId"));
 | 
			
		||||
	string extractId = ctx.request.getPathParamAs!string("extractId");
 | 
			
		||||
	const extractFile = buildPath(EXTRACTS_DIR, extractId, EXTRACT_FILENAME);
 | 
			
		||||
	fileResponse(ctx.response, extractFile, "application/json");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue