#Setup - install Minimacy, as described in the [Setup section](page://2000.100.100). Build Minimacy or use the Release distribution. - clone the demo repository: >git clone https://github.com/ambermind/http-time-server.git We assume now that: - [minimacy] is the full path of the Minimacy directory, it contains at least these subfolders: ./bin ./rom ./programs - [minimacyBinary] is the full path of Minimacy binary (minimacy.exe on Windows, minimacy on Unix, minimacyMac on MacOS). - [http-time-server] is the full path of this example on your disk Then, you may start this example with: >[minimacyBinary] [http-time-server]/boot.mcy Alternately, you may replace the content of [minimacy]/programs with the content of [http-time-server]. It will overwrite 'boot.mcy'. You should create a dedicated copy of Minimacy in order to do so. #Usage Once started, the terminal should display: >Local http server started on port 1234. Open http://127.0.0.1:1234 Open your favorite browser, and type [http://127.0.0.1:1234](http://127.0.0.1:1234) You get a basic html web page showing the current time, and providing alternative links: [](html) The Json view looks like this: [](html) The analog view looks like this: [](html) The digital view looks like this: [](html) #Implementation The Http server is started with the following code: fun main()= let 1234 -> port in let httpSrvStart( nil, // no tls key => we use http nil, // no ip local address => the server is bound to all local addresses port, lambda(h, verb, uri)= match uri with // call the rendering function depending on the uri. Each rendering functions returns a string "/" -> timeText(h), "/json" -> timeJson(h), "/digital" -> timeDigital(h), "/analog" -> timeAnalog(h) ) -> httpsrv in echoLn if httpsrv==nil then "Cannot start http server" else strFormat("Local http server started on port *. Open http://127.0.0.1:*", port, port);; The last argument of [[httpSrvStart]] is a lambda function which will be called on each http request. It is expected to return the html response body as a string. Its parameter are: - h: a handler on this request, it may be used to retrieve http parameters, configure the response, for example to set a code (200 is the default). - verb: the http verb of the request - uri: the uri of the request We use a [[match]] to route the different uris to their dedicated function. Each of these function will return the full html response body. The main uri returns the current time and the 3 links: fun timeText(h) = strBuild([ fullDate(time()), "
Alternative views: json analog digital" ]);; [[strBuild]] is a convenient way to concatenate many elements into a single string. As you can see we build a rough html response, without header or anything else. For the Json we need to specify the mime-type, calling [[httpSrvSetHeader]] on the request handler 'h'. fun timeJson(h) = httpSrvSetHeader(h, "Content-Type", "application/json"); let time() -> t in let date(t) -> [year, month, day, weekDay, hour, minute, second] in jsonEncodePretty( jsonObject ["timestamp", jsonInt(t)]:: ["year", jsonInt(year)]:: ["month", jsonInt(month)]:: ["day", jsonInt(day)]:: ["weekDay", jsonInt(weekDay)]:: ["hour", jsonInt(hour)]:: ["minute", jsonInt(minute)]:: ["second", jsonInt(second)]:: nil);; Then we create a jsonObject with a list of [field, json_value]. We call [[jsonEncodePretty]] to convert this Json object into a readable string. For the Analog page, we perform some graphics. We want to return a 400x400 pixels bitmap as a png file. In order to draw the hands, we need a conversion function which returns x,y coordinates from angular, radius: // coordinates transformation, from angular to xy fun _xyCoordinates(scale, alpha) = [200 + intFromFloat(scale *. sin(alpha)), 200 - intFromFloat(scale *. cos(alpha))];; Minimacy has precise typing of numbers: integer are not floating numbers. Alpha and scale are float s, but coordinates are integers. '*.', cos, sin work with floats while '+' and '-' operate with integers. Coordinates are returned as a tuple of two integers. Then we declare a function to draw a single hand as a triangle, with an orientation and a size (aka scale): // hands are drawn as green triangles fun _drawHand(bmp, scale, alpha) = let _xyCoordinates(scale, alpha) -> [x1, y1] in let _xyCoordinates(20., alpha+. 3.) -> [x2, y2] in let _xyCoordinates(20., alpha-. 3.) -> [x3, y3] in ( bitmapLine(bmp, x1, y1, x2, y2, 0x00ff00, nil); bitmapLine(bmp, x2, y2, x3, y3, 0x00ff00, nil); bitmapLine(bmp, x3, y3, x1, y1, 0x00ff00, nil) );; Colors are provided as 32 bits ARGB integers. Here 0x00ff00 is pure green at full intensity. Now we can write the function which specifies "image/png" as the mime-type, get the current angulars of the hour and minute hands. fun timeAnalog(h) = httpSrvSetHeader(h, "Content-Type", "image/png"); let date(time()) -> [year, month, day, weekDay, hour, minute, second] in let floatFromInt(minute)*. 2. *. pi /. 60. -> minute in // convert minutes to radiant angle let floatFromInt(hour)*. 2. *. pi /. 12. +. (minute /. 12.) -> hour in // convert hours to radiant angle let bitmapCreate(400, 400, 0x404040) -> bmp in ( bitmapCircle(bmp, 20, 20, 360, 360, 0x00ff00, nil); _drawHand(bmp, 100., hour); _drawHand(bmp, 150., minute); pngFromBitmap(bmp, false) );; The last function [[pngFromBitmap]] takes a bitmap and a boolean and returns the png encoding as a string. The boolean indicates whether the png contains an alpha layer. For the digital page, we first need a Font to draw the text. const Font=fontFromBitmap(bitmapFromPng(load("rsc/fonts/Arial_32_256.png")));; We load such a font from a bitmap you will found in ./minimacy/rom/rsc/fonts/Arial_32_256.png Fonction composition could be read like this: - first we [[load]] the file - we assume it is a png file and call [[bitmapFromPng]] to create a bitmap from it - finally we call [[fontFromBitmap]] to make a font from it. More information about these bitmaps in [core.2d.font](page://ref.core.2d.font) and more specificaly in [[fontFromBitmap]]. You may create your own font bitmaps using [FontMaker](https://minimacy.net/book/#/font_maker). Once the font is ready, we can use it to create the digital reply: fun timeDigital(h) = httpSrvSetHeader(h, "Content-Type", "image/png"); let bitmapCreate(500, 40, 0xe0e0e0) -> bmp in ( bitmapText(bmp, 250, 20, ALIGN_CENTER|ALIGN_MIDDLE, fullDate(time()), Font, 0x404040, nil); pngFromBitmap(bmp, false) );; We specify "image/png" as the mime-type, then create a bitmap 500x40 with a light gray background. We draw the date in dark gray. Finally we encode the bitmap as png, and return the resulting string.