📜 ⬆️ ⬇️

N2O: Erlang WebSockets Web Framework

N2O Erlang Framework

INTRODUCTION


This post implies a good intro in N2O in Russian.

What is Erlang / OTP Web Framework N2O and what its chip for web development can be found on the page in github and the official site of SynRC . There, everything as you like with graphs and presentations.
')
And here we consider the principles of the framework and talk about the eternal.

Considered version N2O: 1.1.0
It is always more interesting to see the result, rather than talk about it, I suggest that you first install N2O on your computer and only then delve into its insides. So clearer.

Get answers to your questions and see recommendations can be on the official IRC channel # n2o on FreeNode.net.

INSTALLATION


Install Erlang if it is not installed yet. Installed.

Download N2O, compile and run:

git clone git://github.com/5HT/n2o.git cd n2o/samples make && make console 

We look: 127.0.0.1:8000/

N2O: Erlang Web Framework in Safari

Opening several windows you can chat with yourself.

MANY THEORY


NICHE

It is intended primarily for developing horizontally scalable solutions with low latency for processing client requests.
Online games, chat rooms, instagrams, tweeters - this is not exactly what Erlang was created for, but where you need to use N2O.

Under the hood

N2O is a redesigned Nitrogen project that is a bit sad. In N2O, we have the fastest Web server Cowboy, work through WebSockets, exchange binary data wherever possible, HTML and DTL templates, the minimum amount of JavaScript without using third-party libraries.

Comparison of web frameworks on Erlang can be seen on the link .

Ability to use:

In N2O, source code compilation is implemented on the fly, even without damage to open sessions, based on Sync . Development is becoming more human.
With Sync, you can code without drochilova ( transl .)

Server data exchange with clients is implemented through WebSockets and has a minimal overhead. Possible data transfer formats:

Clustering and resiliency for the Web has become available more than ever before, with maximum ease of development.
_5HT: So that you do not e ___ cya. Your business is clack-clack and production


MODEL OF CONDUCT

N2O is built like Erlang itself in the transfer of messages, but not from process to process, but from client to server. Call it an event model.

We describe the timeline of the N2O embedded example of n2o_sample.
  1. When the page /index requested, the HTML markup described in the function index:body() passed to the browser.
  2. The page runs a javascript that initializes the connection through the WebSocket.
  3. Then, the payload in the form of JavaScript code is transmitted via WebSocket, and the page elements are initialized with data via index:event(init) . Here is one of the roles of JavaScript - for example, to create an event for the button on the client in the form of a JS function that sends information about the click to the server.
  4. After clicking on the button, a Bert-Encoded message arrives on the server under the Base64 mushrooms and the index:event(Term) function is performed where Term is the term described in the button's record field: #button.postback . For example, the #button{postback=sasay} button after pressing will force the function index:event(sasay).
  5. The server, in turn, can also send data to the browser at any time. If the data is sent from another process , then the following conditions must be met: at index:event(init) main process servicing the client (browser tab) must be registered under some name by calling wf:reg/1 , and in process after the end generating the code for updating the page ( wf:insert/2 , wf:wire/1 , etc.) the function wf:flush/1 should be called to send the update code to the browser, where it will then be executed by the JS machine.


The first thing that comes to mind is that the page dynamically changes not based on function calls from a JavaScript file, but based on the received JavaScript from the server in real time.

And this is the native interactive mode for a web application without using crutches like AJAX and LongPooling Comet. The future is here, kittens. His name is WebSockets.

A table of support for WS browsers can be seen here , and check your browser here .

MORE ABOUT THE APPLICATION STRUCTURE


If acquaintance with Erlang happened recently or just that, most likely there will be questions: what is where and in what place does it show your creativity.

image

Highlighted those folders and files that may be subject to editing. Consider the key parts.

n2o_sample

N2O already contains an example of a user application - n2o_sample . n2o_sample is a separate Erlang application that runs on N2O. As can be seen in the picture above, it is located in the apps/ directory - this is a collection of user applications, we can add our own ones there if it is necessary to divide n2o_sample into two or more independent applications.

Also n2o_sample, of course, can be renamed or replaced with something else. But for a start, I would not advise doing this, but using the existing code as a starting point in developing my application.

Application list

When you run n2o_sample, it, as Erlang relies on the application, runs all the applications that it depends on (dependencies from deps/ , and user-defined, if any, from apps/ ). This code is in n2o_sample/src/web_app.erl :

 -module(web_app). -behaviour(application). -export([start/2, stop/1]). start(_StartType, _StartArgs) -> application:start(crypto), application:start(sasl), application:start(ranch), application:start(cowboy), application:start(gproc), application:start(mimetypes), application:start(syntax_tools), application:start(compiler), application:start(erlydtl), application:start(rest), application:start(n2o), web_sup:start_link(). stop(_State) -> ok. 


The web_sup:start_link() function starts the n2o_sample itself.

But if we want to expand this list of dependencies - you need to know that this is not the only place with a listing of applications. You also need to fix two more files: reltool.config and .applist , the latter being created after the first make command in the console. Keep in three places the same thing - a temporary crutch from @ darkproger , but he promised to fix everything (they have been waiting for the promised three years).

sys.config

Parameters for all applications are saved here. In one file. Conveniently. Then from the code we call application:get_env(App,Key) and that's it.

vm.args

Here you can specify the keys for the virtual machine as well as environment variables (instead of $ export SOME_PARAM=value ).

priv / static /

The directory passed to the Cowboy web server as a static file file. Here you can place JavaScript code, throw pikchi and hentai. n2o_sample/src/web_sup.erl :

 dispatch_rules() -> cowboy_router:compile( [{'_', [ {"/static/[...]", cowboy_static, {priv_dir, ?APP, <<"static">>, [{mimetypes,cow_mimetypes,all}]}}, **** 


PAGES


To create dynamic pages, N2O allows you to include HTML files in your project as DTL templates. In the deps/erlydtl/ directory there is an ErlyDTL application which is intended for compiling DTL patterns into Erlang bytecode.

The templates themselves are located in the n2o_sample/priv/templates/ directory and look like HTML files with external data source declarations through words enclosed in double curly braces {{ }} .

Thus, we can “lay out” the HTML layout with static information, and dynamically render the code to Erlang via the {{ }} connection.

For example, consider the body of the login: main / 0 function, which gives the browser the initial state of the page when going to http://127.0.0.1/login/ :

 #dtl{ file = "login", app=n2o_sample, bindings=[ {title,title()}, {body,body()} ]}. 




DEVELOPMENTS


Data exchange in N2O on the client is implemented via JavaScript, with the help of /deps/n2o_scripts/n2o/bullet.js files /deps/n2o_scripts/n2o/bullet.js (initializing the WebSocket connection) and n2o.js (processing the received data).

On the server side, endpoints are: /n2o/src/endpoints/cowboy/bullet_handler.erl (initialization of the WebSocket connection) and n2o_bullet.erl (data exchange).

API


Let us analyze the main API functions with which the most questions arise when meeting with N2O.

wf: comet / 1, wf: async / 1, wf: async / 2

Register the process under a unique name ( “comet” for comet/1 and async/1 ) within the node through global:register_name/2 . If already registered, return its Pid.

wf: flush / 1

Withdraws via wf_context:actions/0 saved in the state of the current process changes for the page and sends them via wf:send/2 process (within the node) whose name is passed in the parameter.

wf: reg / 1, wf: reg / 2 (? REGISTRATOR = n2o_mq)

Register the process as Property under a non- unique name within the node through GProc. Re-registering the process via GProc under the same name will not work, the registration status is stored in the process's stack ( get/1 , put/1 ) and the term skip ( n2o_mq.erl ) will be returned. Additional info in Russian by Gproc here .

The default logger is the n2o_mq module n2o_mq but it can be overridden, for example, to be able to register processes within the cluster.

wf: send / 2 (? REGISTRATOR = n2o_mq)

Sends the message passed to the function by the second argument to the process registered via wf:reg/1 or wf:reg/2 .

wf: q / 1

Retrieves the data transmitted from the client through the so-called postback elements, for example:

 body() -> [ #textbox{ id=message }, #button{ postback={button_pressed}, source=[message] } ]. event({button_pressed}) -> wf:info("Message: ~p",[wf:q(message)]); 

The text contained in the text box at the time the button is pressed will be printed to the console.

wf: qs / 1

Extract parameters from HTTP forms, for example:
wf:qs(<<"x">>) will extract <<"ABC">> if the URL were localhost:8000/index?x=ABC localhost:8000/index?x=ABC .

wf: wire / 1

It can take as an argument both JavaScript text and event codes declared in the “Actions” section of the /n2o/include/wf.hrl file, for example: wf:wire(#alert{text="!"}) . JavaScript will also be wrapped in #wire{actions=JS} , which will result in the wf:wire(#wire{sctions=JS}) construct.

wf: update / 2, wf: insert_top / 2, wf: remove / 1 and others

These are special cases of wf:wire/1 , including ready-made JavaScript code for changing the DOM in the client’s browser.

wf: info, wf: warning, wf: error

These are the functions that are recommended to use, instead of error_logger:info_msg/1 and the rest, respectively.

wf: f, wf: to_list, wf: to_binary, wf: html_encode, wf: url_encode, wf: hex_encode and others

Located in the “Convert and Utils API” /n2o/src/wf.erl file. All of them are add-ons over standard Erlang functions, but smarter and not so wooden. wf:f is an analogue of io_lib:format , then the list of functions-converters accepts any term to the input, then more web-specific functions. It makes no sense to describe them all in detail here, the only purpose was to show that they exist.

wf: pickle / 1, wf: depickle / 1 (? PICKLER = n2o_pickle)

Encoder and term decoder for transferring system calls between client and server. n2o_pickle encodes in Base64, while n2o_secret uses AES / RIPEMD160 encryption with a random key.

On this API everything, additional information can be found from the official docks on the N2O API .

MUST PAY ATTENTION


Below are the free SynRC software products that can speed up the output of your project to Erlang by tens of times.

KVS

KVS is an abstract KV noSQL database model that can feed table subsets via doubly linked lists and secondary indexes ( kvs:index/3 ). Currently available with Mnesia, RIAK and KAI.

AVZ

AVZ - authorization system through Twitter, Google, Facebook, Github and Microsoft.

Shen

Shen is an Erlang interpreter of JavaScript code. Allows you to use the Erlang compiler to validate JavaScript.

Mqs

MQS - MQ library for RabbitMQ.

Feeds

Feeds - handler of the command pool for maintaining data consistency on all nodes of the cluster, also a cache server.

Skyline

SkyLine is an example of an online store on N2O.

COUNTACH

Countach is a social system and advanced app store. Production-ready. Uses KVS, AVZ and Feeds. Based on VOXOZ.

VOXOZ

VOXOZ - Open Erlang cloud platform (PaaS). Uses Docker, ErlangOnXen. More information on blog.docker.io .

CONCLUSION


So that information is assimilated evenly, this is all for now. Special thanks to @ mtreskin for the advice on choosing the architecture and targeting nitrogen and n2o; as well as @ 5HT for endless 24/7 consultation at IRC.

Source: https://habr.com/ru/post/220841/


All Articles