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
 | 
					*.obj
 | 
				
			||||||
*.lst
 | 
					*.lst
 | 
				
			||||||
*.jar
 | 
					*.jar
 | 
				
			||||||
 | 
					extracts/
 | 
				
			||||||
							
								
								
									
										2
									
								
								dub.json
								
								
								
								
							
							
						
						
									
										2
									
								
								dub.json
								
								
								
								
							| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
	"copyright": "Copyright © 2023, Andrew Lalis",
 | 
						"copyright": "Copyright © 2023, Andrew Lalis",
 | 
				
			||||||
	"dependencies": {
 | 
						"dependencies": {
 | 
				
			||||||
		"handy-httpd": "~>7.6.1",
 | 
							"handy-httpd": "~>7.6.3",
 | 
				
			||||||
		"slf4d": "~>2.4.1"
 | 
							"slf4d": "~>2.4.1"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"description": "HTTP server for generating schematic materials lists.",
 | 
						"description": "HTTP server for generating schematic materials lists.",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	"fileVersion": 1,
 | 
						"fileVersion": 1,
 | 
				
			||||||
	"versions": {
 | 
						"versions": {
 | 
				
			||||||
		"handy-httpd": "7.6.1",
 | 
							"handy-httpd": "7.6.3",
 | 
				
			||||||
		"httparsed": "1.2.1",
 | 
							"httparsed": "1.2.1",
 | 
				
			||||||
		"slf4d": "2.4.1",
 | 
							"slf4d": "2.4.1",
 | 
				
			||||||
		"streams": "3.5.0"
 | 
							"streams": "3.5.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
const form = document.getElementById("schematic-form");
 | 
					const form = document.getElementById("schematic-form");
 | 
				
			||||||
 | 
					const resultContainer = document.getElementById("result-container");
 | 
				
			||||||
form.onsubmit = async (e) => {
 | 
					form.onsubmit = async (e) => {
 | 
				
			||||||
    e.preventDefault();
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					    resultContainer.innerHTML = "";
 | 
				
			||||||
    console.log(e);
 | 
					    console.log(e);
 | 
				
			||||||
    const data = new FormData(form);
 | 
					    const data = new FormData(form);
 | 
				
			||||||
    console.log(data);
 | 
					    console.log(data);
 | 
				
			||||||
| 
						 | 
					@ -10,9 +12,12 @@ form.onsubmit = async (e) => {
 | 
				
			||||||
            body: data
 | 
					            body: data
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        const result = await response.json();
 | 
					        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();
 | 
					        form.reset();
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
        console.error("Error: " + 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/>
 | 
					        <input id="schematic-file-input" name="schematics" type="file" multiple accept=".nbt" required/>
 | 
				
			||||||
        <button type="submit">Submit</button>
 | 
					        <button type="submit">Submit</button>
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
 | 
					    <div id="result-container">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
    <script src="files.js"></script>
 | 
					    <script src="files.js"></script>
 | 
				
			||||||
</body>
 | 
					</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 handy_httpd.handlers.file_resolving_handler;
 | 
				
			||||||
import slf4d;
 | 
					import slf4d;
 | 
				
			||||||
import slf4d.default_provider;
 | 
					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() {
 | 
					void main() {
 | 
				
			||||||
	auto provider = new shared DefaultProvider(true, Levels.INFO);
 | 
						auto provider = new shared DefaultProvider(true, Levels.INFO);
 | 
				
			||||||
| 
						 | 
					@ -15,7 +21,7 @@ void main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PathDelegatingHandler handler = new PathDelegatingHandler();
 | 
						PathDelegatingHandler handler = new PathDelegatingHandler();
 | 
				
			||||||
	handler.addMapping("POST", "/extracts", &handleExtract);
 | 
						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);
 | 
						FileResolvingHandler fileHandler = new FileResolvingHandler("site", DirectoryResolutionStrategies.serveIndexFiles);
 | 
				
			||||||
	handler.addMapping("/**", fileHandler);
 | 
						handler.addMapping("/**", fileHandler);
 | 
				
			||||||
| 
						 | 
					@ -23,15 +29,46 @@ void main() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void handleExtract(ref HttpRequestContext ctx) {
 | 
					void handleExtract(ref HttpRequestContext ctx) {
 | 
				
			||||||
	MultipartFormData data = ctx.request.readBodyAsMultipartFormData();
 | 
					 | 
				
			||||||
	infoF!"Read %d files: "(data.elements.length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	import std.json;
 | 
						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;
 | 
							JSONValue result = JSONValue.emptyObject;
 | 
				
			||||||
	result.object["extractId"] = JSONValue(42);
 | 
							result.object["extractId"] = JSONValue(extractId.toString());
 | 
				
			||||||
		ctx.response.writeBodyString(result.toJSON(), "application/json");
 | 
							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) {
 | 
					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