11

I learned some codes to make a mini HTTP server in MMA way here.

server=SocketListen[8000,Function[{assoc},Block[{client=assoc["SourceSocket"]},
Block[{html,expr},
expr=First@StringCases[assoc["Data"],RegularExpression["GET /\\?expr=([^ ]+)"]->"$1"];
html=ToString@InputForm@ToExpression@URLDecode@expr;
WriteString[client,"HTTP/1.1 200 OK\r\nDate: "<>DateString[]<>"\r\nContent-Type: text/html\r\nContent-Length: "<>
ToString@StringLength@html<>"\n\n"<>html];
Close[client]]]]]

do not forget to close it when finished.

DeleteObject[server]
Close[server["Socket"]]

by the upper codes, we could pass exprs to MMA and get results in TEXTs way, I want to know how to show the Plots or Graphics with these codes in web browsers like Chrome? I wonder that, MMA could be used as web server, there should be some frameworks to help this becoming true, like Express upon node.js. is this worth to do sth? enter image description here

enter image description here

Kuba
  • 136,707
  • 13
  • 279
  • 740
Jerry
  • 2,459
  • 9
  • 15
  • 1
    Perhaps ExportString[expr,"PNG"] and changing the response content-type to image/png might work. – Carl Lange Jan 18 '19 at 18:18
  • 1
    Export string to HTMLFragment can help on both TEXT or PLOTs if set Content-Type value text/html – Jerry Jan 19 '19 at 02:44
  • 2
    !!!WARNING: Injection risk comes true if exposed in network. Similarly, I remembered Exit[] executed when WloframAlpha firstly lanched as public knowledge engine. – Jerry Jan 19 '19 at 02:48

2 Answers2

9

Very often SVG makes sense, it will scale well with magnification. This idea does not deserve a separate answer so additionally I rewrote the code in a more idiomatic style:

server = SocketListen[8000
, Function[{assoc}
  , Module[
      { client = assoc["SourceSocket"], inputString, response}

    , inputString = ImportString[assoc["Data"], "HTTPRequest"] @ "Query" // Lookup["expr"]

    ; response = GenerateHTTPResponse @ ExportForm[
        ToExpression[inputString], "SVG"
      ]

    ; WriteString[client, ExportString[response, "HTTPResponse"]]

    ; Close @ client
    ]
  ]      
]

enter image description here

(* DeleteObject[server]
   Close[server["Socket"]]
*)
Kuba
  • 136,707
  • 13
  • 279
  • 740
8

You can get it to respond with images by doing the following:

server = SocketListen[8000, 
  Function[{assoc}, 
   Block[{client = assoc["SourceSocket"]}, 
    Block[{html, expr}, 
     expr = First@
       StringCases[assoc["Data"], 
        RegularExpression["GET /\\?expr=([^ ]+)"] -> "$1"];
     response = ExportString[ToExpression@URLDecode@expr, "PNG"];
     WriteString[client, 
      "HTTP/1.1 200 OK\r\nDate: " <> DateString[] <> 
       "\r\nContent-Type: image/png\r\nContent-Length: " <> 
       ToString@StringLength@response <> "\n\n" <> response];
     Close[client]]]]]

I've made 2 changes - first is to change the response Content-Type to image/png. Otherwise the browser doesn't know the response is an image.

Next I used ExportString[..., "PNG] to get MMA to respond with the string representation of an image, which, when coupled with the Content-Type change, will render correctly in a browser, as below.

working for images

To your broader question - in my opinion, to make this a real-live web server is a ton of work and probably not worth it when CloudDeploy and family exist.

Carl Lange
  • 13,065
  • 1
  • 36
  • 70
  • Thanks! It's helpful to build a math webservice at least, while CloudDeploy depends on the Clould service. – Jerry Jan 18 '19 at 18:35
  • I agree and I definitely think it would be cool! Be aware that it probably doesn't comply with your license if you open it up to the web at large. My license doesn't allow "Any type of remote access" to my subscription which you could probably put this under if you were a legal type :) – Carl Lange Jan 18 '19 at 18:41
  • Surely, professional license is necessary to be applied, if worth to make the best use of the functions although it's expensive.:) – Jerry Jan 19 '19 at 00:32