Web Development in the Wolfram Language

Carlo Barbieri, Riccardo Di Virgilio (Advanced Research Group)

Join the Conversation #WolframTechConf

Local development in the Wolfram Language

New in 10.3

HTTPResponse — a completely redesigned representation of an HTTP response

GenerateHTTPResponse — generate an actual HTTP response from APIFunction, etc.

Upcoming features

URLDispatcher — simple and powerful URL routing

WebServer — test your deployments locally

HTTPResponse

HTTPResponse has a convenient standard form that can be used to quickly inspect its content:

response =HTTPResponse[
"<h1>Hello <em>world</em>!</h1>", 
"ContentType" -> "text/html"
]

HTTPResponse is an object with easily accessible properties.

response["Properties"]

response["StatusCodeDescription"]

The circle changes color according to the status code:

HTTPResponse["bad", "StatusCode"-> 400]

HTTPResponse["worse", "StatusCode"-> 500]

GenerateHTTPResponse

Works with: APIFunction, FormFunction, Delayed, ExportForm, ResponseForm

GenerateHTTPResponse can be used to simulate the behavior of deployed objects locally

GenerateHTTPResponse[Delayed[RandomImage[], "HTML"]]

CloudDeploy[Delayed[RandomImage[], "HTML"]]

You can use the second argument to set the parameters of the HTTP request:

api = APIFunction["x" -> "Integer", #x!&, "JSON"];

GenerateHTTPResponse[api]["Body"]

GenerateHTTPResponse[api, "Query" -> {"x" -> "10"}]["Body"]

New in cloud objects

GenerateHTTPResponse allows us to do things that were previously impossible or needlessly complicated with CloudObjects. For example having an API return a Form or an API depending on the parameters.

dynamicAPI = Delayed[
If[
Lookup[HTTPRequestData["Query"], "_mode"] === "api",
APIFunction["x" -> "String"],
FormFunction["x" -> "String"]
]
];

CloudDeploy[dynamicAPI]

There is a bunch of new cool things you can do:

CloudDeploy[Delayed[FormFunction["x" -> "String", FormTheme -> If[Now < Sunset[Today], "Red", "Black"]]]]

URLDispatcher

URLDispatcher is a simple URL router:

$Rules = URLDispatcher[{
"/api" -> APIFunction["x" -> "String"],
"/form" -> FormFunction["x" -> "String"]
}];

You can use it do more powerful stuff by using string matching and replacement rules:

$Rules = URLDispatcher[{
"/" ~~ id:DigitCharacter.. ~~ EndOfString :> HTTPRedirect["http://www.imdb.com/title/tt" <> id <> "/"]
}];

GenerateHTTPResponse[$Rules, "/123"]

GenerateHTTPResponse[$Rules, "/not-good"]

A more complex example

$VaticanSite = URLDispatcher[{
	"/contact-us/" -> FormFunction[
		{"email" -> "EmailAddress", "message" -> "TextArea"},
		Style["Thank you for contacting us!", 30]&,
		"HTML"
	],
	"/how-to-find-us/" -> FormPage[
		{"position", None} -> "Location",
		Grid[Values[Normal[TravelDirections[
			{#position, (Entity["Vatican City", Entity["Country","VaticanCity"], "Entity[\"Country\", \"VaticanCity\"]", "country"])},
			"Dataset"
		][All, {"Description", "Distance"}]]], Alignment -> Left]&,
		{"Form", "Button", GeoGraphics[(Entity["Vatican City", Entity["Country","VaticanCity"], "Entity[\"Country\", \"VaticanCity\"]", "country"])]} -> {"Form", "Button", "Result"}
	],
	"/popetrait/" -> APIFunction["pope" -> "Person", ImageEffect[ImageResize[#pope["Image"], 300], {"OilPainting", 3}]&, "HTML"],
	"/" ~~ lang:LetterCharacter... ~~ EndOfString  :> Delayed[
		TemplateApply[
			"<h1>``!</h1>
			 <img src='``' width='400'/>
			 <br/>
			 <br/>
			 Previously on Vatican:<br/>
			 <a href='/popetrait/?pope=paul+vi'>Paul VI</a> - 
			 <a href='/popetrait/?pope=john+paul+i'>John Paul I</a> - 
			 <a href='/popetrait/?pope=john+paul+ii'>John Paul II</a> - 
			 <a href='/popetrait/?pope=benedict+xvi'>Benedict XVI</a>
			 <hr/>
			 <a href='contact-us/'>Contact us</a> - <a href='how-to-find-us/'>How to find us</a>
			 <br/>
			 &copy; Civitas Vaticana - Annus Domini MMXV",
			{
				Replace[
					Interpreter["Language"][lang], {
						_Missing|_Failure -> "Welcome",
						l_ :> Capitalize[RandomChoice[WordTranslation[
							"welcome",
							(Entity["English", Entity["Language","English"], "Entity[\"Language\", \"English\"]", "language"]) -> l
						]]]
					}
				],
				RandomChoice[Import["https://www.google.com/search?q=pope+francis&es_sm=119&source=lnms&tbm=isch&sa=X&ved=0CAgQ_AUoAmoVChMI3_Kyo77RyAIVQZmACh2hiAs2&biw=1300&bih=671",{"HTML","ImageLinks"}]]
			}
		],
		{"HTML", "FullDocument" -> True}
	]
}];

But this is almost impossible to debug by just running GenerateHTTPResponse, so we built a tool to locally test your deployments using a local HTTP server.

You can start a local webserver by doing:

StartWebServer[$VaticanSite]

Changing the value of $VaticanSite has an immediate effect as the server is running asynchronously on the same kernel.

$VaticanSite = ExportForm[Style["The Vatican is now closed for holidays, check back with us soon!", 30], "HTML"];

$VaticanSite = ExportForm[Style["Site under Maintenance", 30], "HTML"];

A list of rules is effectively equivalent to URLDispatcher

$VaticanSite = {
"/" ~~ id:DigitCharacter.. ~~ EndOfString :> HTTPRedirect["http://www.imdb.com/title/tt" <> id <> "/"]
};

SystemOpen["http://localhost:7000/"]

Conclusions and outlook

New and improved in 10.3: HTTPResponse, GenerateHTTPResponse

The new HTTPResponse has all the information you need at your fingertips

GenerateHTTPResponse is the new mechanism we use internally for defining the behavior of active CloudObjects, but you can use it locally to simulate their behaviour

Upcoming: URLDispatcher, local WebServer

URLDispatcher is a very simple URL router, that uses all the power of the Wolfram Language string matching

WebServer is an extremely powerful tool for rapid debugging of cloud apps and we’re already using it extensively internally

We’re striving to build a complete toolkit to allow both power users and novices to build a complete modern website in the Wolfram Language

We’d love to hear your suggestions and requests