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