Dyalog/MiServer

Documentation for Producing Non-HTML MIME types?

arcfide opened this issue · 3 comments

I am having trouble finding documentation on the supported interface for producing non-HTML MIME-types from a MiPage. Specifically, I am looking for a way to produce, say, a Text document, or something else, on certain inputs, but an HTML page on others. Is there a supported way to do this? Is this documented anywhere?

Currently MiPages produce only HTML. There's a lot of integral infrastructure that automates the rendering of the html, head, and body elements to alleviate the user having to manage them. For instance, the Add method in a MiPage looks at what's being added and determines whether it belongs in the head or body element.

Non-HTML MIME types are supported by requesting files with extensions other than .mipage, in which case we attempt to look up the appropriate setting for 'content-type' based on the file's extension. But that requires the content to be in a file.

I assume you're asking for this because you want to generate the content on the fly? Otherwise, writing the data to file and making a request for the file rather than a MiPage would work.

I can see a way to make this work with relatively little modification.

:Class index : #.MiPage
    ∇ Compose
      :Access public      
      _Request.SetContentType '.json' ⍝ or 'content-type' _Request.SetHeader 'application/json'
      Add ⎕JSON ⍳10
    ∇ Compose
:EndClass  

Then MiServer could detect if the content-type header has been set and if it's not text/html, then we render the contents of the body element, but not wrap them in the HTML tag.

I can see one other way to make this work without any modification to MiServer. Basically, generate your content, write it to file, and make the rendered MiPage load the file. Of course, you'd then need to manage cleaning up the files you wrote, but that's not terribly complicated.

:Class index : #.MiPage
    ∇ Compose
      :Access public
      OnLoad←'window.location.href="data.json"'
      (⎕JSON⍳10)⎕NPUT(#.Boot.AppRoot,'data.json')1
    ∇
:EndClass

Let me know if the latter solution works for you.

I can see a way to make this work with relatively little modification.

Are you saying that this is not implemented yet? I do need to dynamically generate the files, so just referencing a file will not work. I can potentially generate files and then link to them, but that might introduce race conditions in certain workloads, so it would be nice to be able to do this without being forced to go to the filesystem.

I will give the filesystem approach a try, but if the first approach is implemented, that seems like a better one.

That's right. MiServer was initially designed as a means for users to:

  • host their applications on the web
  • provide a GUI on non-Windows platforms
  • have one code base to deliver their applications cross-platform.

without needing extensive knowledge about HTML, CSS, etc. So, the MiPage class, which is based on HtmlPage, which is based on HtmlElement was always intended to serve HTML content.

However, having said that, I just remembered that when I implemented RESTful support for MiServer, I created another page template, RESTfulPage, that should work for you...

Instead of a Compose method, RESTfulPage requires a Respond method which returns the content to be sent back to the client. By default, you can return APL data and MiServer will convert it to JSON format, flattening any arrays of rank>1.

:Class index : #.RESTfulPage
    ∇ r←Respond
      :Access public
      r←3 3⍴⍳9
    ∇
:EndClass

will return
[[1,2,3],[4,5,6],[7,8,9]]

You can also set the content-type and return whatever you want.

:Class index : #.RESTfulPage
    ∇ r←Respond
      :Access public
      SetContentType'text/csv'
      r←'"Drake","Mallard",42',(⎕UCS 10),'"Mickey","Mouse",107'
    ∇
:EndClass

I think this should meet your needs?
I made a couple of minor changes so you should pull the 04a37e5 commit or later.