adamdruppe / arsd

This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo.
http://arsd-official.dpldocs.info/arsd.html
530 stars 127 forks source link

Request: Make cgi.d work with TiddlyWiki (includes my hack to make it work) #271

Closed bachmeil closed 3 years ago

bachmeil commented 3 years ago

Background: I wanted a simple way to use cgi.d with TiddlyWiki. If you're not familiar with it, the brief version is that it's a single file app that can be used as a wiki but also other things. You make your edits in the browser and then save them in the file itself. The modern incarnation is kind of clumsy to use, so I thought I'd use cgi.d to fix that problem.

Problem 1 cgi.d doesn't handle a request of type text/html. Here's my full program:

import arsd.cgi;
import std.stdio;

void hello(Cgi cgi) {
  if (cgi.pathInfo == "/empty") {
    cgi.header("x-api-access-type: file");
    cgi.header("dav: tw5/put");
    if (cgi.requestMethod.to!string == "PUT") {
      toFile("empty.html", cgi.postJson);
    } else if (cgi.requestMethod.to!string == "GET") {
      import std.file;
      cgi.write(readText("empty.html"));
    }
  } else {
    cgi.write("Why are you here?");
  }
}
mixin GenericMain!hello;

void toFile(string name, string txt) {
  import std.file;
  std.file.write(name, txt);
}

The relevant part when TiddlyWiki saves is this:

if (cgi.requestMethod.to!string == "PUT") {
  toFile("empty.html", cgi.postJson);
}

TiddlyWiki saves by making a PUT request in text/html format. I get the error:

object.Exception@cgi.d(1258): unknown request content type: text/html

All I had to do to make it work was add

} else if(pps.contentType == "text/html") { // FIXME: what if we used this as a fallback?
  pps.isMultipart = false;
  pps.isJson = true; // FIXME: hack, it isn't actually this

before line 1258. No idea if that's a proper fix, but it works for me - it saves the data from the PUT request sent by TiddlyWiki into cgi.postJson.

Problem 2 I had to create the separate function toFile in order to save the updated file. Not sure if that's the intended behavior, but std.file.write doesn't work inside the GenericMain function.

adamdruppe commented 3 years ago

Your problem 1 fix there is about right, I should just rename it to like postBody or something (with postJson as an alias for compat), I just never decided if I should support that but there's no reason not to.

For problem 2... you sure that's just just a scope thing? did you use the full name: std.file.write("filename.html", content); ? Cuz I've done similar before, it should work.

bachmeil commented 3 years ago

I just retried and changing the toFile call to std.file.write does work. The odd thing is that previously it was creating the file if it didn't exist, but didn't write anything to the file, so I thought something was happening to the output stream. Anyway, it works now.

adamdruppe commented 3 years ago

OK, I'm on a work call right now but shortly after that I can commit the other thing for the future.

adamdruppe commented 3 years ago

Can you try this? https://github.com/adamdruppe/arsd/commit/0b65fca65186b5a9ac61cf075b1f2155012c9e27 (just grab the master branch file as i pushed there)

It should work without breakage, but also do the postBody more generically for more flexibility.

bachmeil commented 3 years ago

I'll give it a try.

bachmeil commented 3 years ago

I tested it for all the different ways I use TiddlyWiki, and it works, both the code I posted above and my new code, which is here in case you want to see my changes:

import arsd.cgi;
import std.file, std.stdio;

void hello(Cgi cgi) {
  if (cgi.pathInfo == "/empty") {
    cgi.header("x-api-access-type: file");
    cgi.header("dav: tw5/put");
    if (cgi.requestMethod.to!string == "PUT") {
      std.file.write("empty.html", cgi.postBody);
    } else if (cgi.requestMethod.to!string == "GET") {
      cgi.write(readText("empty.html"));
    }
  } else {
    cgi.write("Why are you here?");
  }
}
mixin GenericMain!hello;

Thanks for updating this so fast!

adamdruppe commented 3 years ago

nice! looks pretty good.

bachmeil commented 3 years ago

I'm going to write up a post for my website. I'll let you know when it's done. I might even try to turn this into a Dub package. TiddlyWiki is kind of popular.

bachmeil commented 3 years ago

Repo: https://github.com/bachmeil/tiddlyd