Have you seen the famous "Apache vs. Yaws" picture? Are you thinking that you should use the yaws too? The first impression of these figures is that Yaws has an incredibly big advantage in scalability, which can scale to 80,000 parallel connections, and Apache cannot continue to support it with only 4,000 connections. There is a clear divergence in the response to these graphs, a voice that says "These graphs are unlikely to be accurate" or "they must not be properly configured for Apache"; the other sounds the opposite, "Wow, I'm going to try yaws!." ”
Whether or not you believe in the Yaws comparison chart above, Yaws is indeed a reliable web Server that can handle dynamic content. Claes Wikström developed Yaws with Erlang, "another Web server (yet another Web server)." Erlang is a programming language specifically designed to support long-running, concurrent, and highly reliable distributed systems. (To learn more about Erlang, you can see the wonderful "programming Erlang", whose author is the founder of the Erlang language,--joe Armstrong. The flexibility of yaws and the combination of the many unique features of Erlang make them a restful Web service platform that can not be overlooked. If you're dealing with a static page, try lighttpd or nginx, but if you're writing a dynamic, RESTful Web service, then Yaws is definitely worth trying. In this article, I'll cover some of my experience in developing Web services using Yaws and Erlang.
Yaws Foundation
Yaws provides several ways to handle dynamic Web content and support RESTful Web services:
-
embed Erlang code in a static page. in this way, you can add
The .yaws
is the extension, which notifies yaws to process it, and ...
The label is replaced with the result of executing the out/1
is a function of the number of tuples (arity) 1, for example, a function with one parameter. This parameter should be a yaws , arg
record, which is a special data structure Yaws uses it to pass the details of the requests received to the code that handles them. For example, a arg
Record can provide request URI, request header, post
data and other information.
Application Module (APPMOD). because of the appmod of Yaws, the application code can control the URI. In the method described earlier, the Erlang code is embedded in a static file whose URIs are determined by their path relative to the document root of the Web server. However, with Appmod, the application controls the meaning of the URI, which is usually not associated with artifacts on any file system. Appmod is basically an out/1
Erlang module that exports functions. These modules are configured in the Yaws configuration file to associate a URI path element. If a request contains a path element associated with a registered Appmod, Yaws calls the record of the module out/1
arg
. The function of the module out/1
can continue to interpret the remainder of the URI to explain what the specific resource for the request and response target is.
yaws Application (Yapp). Appmods is usually just a single Erlang module, Yaws Yapp is a full-featured application, unlike this. Each yapp has its own document root, and it has its own set of Appmod. To be clear, Yapp is the ERLANG/OTP application. OTP means "Open Telecom Platform (Development telecom platform)", which is a series of tested libraries and frameworks that bring powerful capabilities to the Erlang program. OTP encapsulates a number of patterns and methods for building distributed, event-driven, high-availability systems. ERLANG/OTP has been proven in the real world, and they can be used in different telecommunication systems, for example, some systems claim that their downtime is only a few milliseconds per year.
These three methods, which can be found in details on the Yaws site, can be effectively applied to restful Web service. The specifics depend on the characteristics of the service itself. But in my experience, Yapp and Appmod are best used because they provide maximum control over Web applications.
Rest-style design
Now that we're going to develop restful web services, let's look at the details of rest. The full name of rest is "representational state transition" (representational Transfer). In his paper, Dr. Roy T. Fielding first introduced the term "REST", which is used to describe an architectural style for highly scalable distributed systems such as the Web. HTTP is essentially an implementation of rest. The term "representational state transition" refers to a restful system that accomplishes a variety of operations by exchanging the representation of the State of resources between requests and responses. For example, for a typical Web page obtained from HTTP GET, it is an HTML representation of a Web resource, identified by a URI, and triggered by a get.
There are a few things to keep in mind when developing restful Web services:
Resource and Resource Identifiers
Supported methods for each resource
The format in which data is exchanged between the client and the server
Status code
HTTP headers for each request and response
Let's focus on Yaws and Erlang, and take a look at some of the issues listed above.
Resource Identifiers
When designing RESTful Web services, you need to consider the resources that comprise the services, such as how best to identify them, and how one relates to the other. The rest-type resource is identified by a URI. Typically, resources have a URI that is related to themselves and share a common path element. For example, in a Web-based bug tracking system, all of the "Phoenix" items (a fictitious project) in the bug can be http://www.example.com/projects/Phoenix/bugs/
found, as long as a bug number can be specified, such as the URI of the bug 12345 may be http://www.example.com/projects/Phoenix/bugs/12345/
. RESTful resources can also provide URIs for other resources within their state representation. For a user who obtains a specific resource state, the returned URI (included in the state representation) can be used to navigate to other parts of the entire web app.
In Yaws, the arg
record specifies the URI of the request, which yaws_api
can be easily obtained using the method provided by the module request_url
:
Out (ARG)
Uri = Yaws_api:request_url (ARG),
Once you get the request URI, you can easily cut the request path as above, which should be split by "/". After you cut a word, you can get a list of the path elements, starting with the root node of the appmod. For example, suppose we bind a appmod to the "projects" path element, the full URI is http://www.example.com/projects/
. If the prefix of a request URI is the preceding URI, then the Appmod out/1
function obtains a detached list of path elements that represents the requested target resource. For example, a URI is a http://www.example.com/projects/Phoenix/bugs/
request that, after executing the preceding section of code, the path variable holds a list of the following path elements:
["Projects", "Phoenix", "Bugs"]
The advantage of separating URIs is that it simplifies further forward work, thanks to the pattern-matching capabilities of Erlang. For example, we can write a function, for example out/2
, to define its function head as follows, and it can handle this particular URI:
% code to handle the This URI is goes here.
This out/2
function can handle all requests that are related to the bug list in all known projects. The project variable appears in the method body and its value is set to the name of the project being requested. Supporting additional URIs is also very simple: out/2
add more variables to the function. If you don't like out
the name of the function, you can change it arbitrarily, because the Yaws framework does not call them directly.
Note that the proper definition of resource URIs can have a huge benefit. With Appmod and Yapp, it's very easy to have a huge, rich URI space, because it's fairly straightforward to bind different appmod to different URI path elements, or to forward requests. The pattern matching of Erlang reduces the difficulty of processing different URI requests. This contrasts with the clumsiness of traditional non-restful services in dealing with this problem, which provides the same URI for all services. In general, this URI points to a script that determines where the request is actually forwarded by requesting the information of the body itself or the URI query string. This traditional technology-based URI seems to have a never-ending argument, compared to the one shown earlier, based on the erlang/yaws forwarding technology, the URI is much clearer.
Resource methods
Methods on Web resources that Web clients can invoke are defined by the verbs of HTTP, mainly including GET
,, PUT
, POST
DELETE
. However, some resources can only support part of these verbs. When you are designing a Web service, you need to determine which methods each resource supports, and remember that RFC 2616 defines the semantics that each HTTP verb expects.
Yaws can http_request
find the request method in the record, which can be arg
easily obtained by logging:
method = (Arg#arg.req) #http_request. method
It returns Erlang Atom, which represents the request method, which can be added to the pattern-matching forwarding method. We can out
add a new parameter to the function to contain the requested method, so we have out/3
:
Out (Arg, "GET", ["Projects", Project, "Bugs"])
The% code to handle GET-this URI is goes here.
The out
variant of this function is only able to handle requests for a list of bugs for each item GET
. Another variant can be processed POST
, perhaps through it, to add a new bug to the list. If you want to allow GET
and POST
request only, and reject other actions, you can write a uniform processing function for the URI:
Out (Arg, "GET", ["Projects", Project, "Bugs"])
% code to handle GET the URI goes here;
Out (Arg, "POST", ["Projects", Project, "Bugs"])
% code to handle POST for this URI goes here;
Out (Arg, _method, ["Projects", _project, "Bugs"])
[{status, 405}].
Here, GET
and POST
outside of the method will match the third variant, it will return an HTTP status code 405
, meaning "method not allowed". Because Method
and Project
variables are not used in methods, underlining them in front of them can turn off the compiler's warning.
Like URI forwarding, Erlang pattern matching makes it easy for developers to forward different HTTP verbs to different functions.
Presentation format
When designing RESTful Web services, you need to consider what appearances each resource supports. For example, Web service resources typically support XML or JSON imagery. Erlang provides a handy JSON module for the Xmerl library, which can be created and read xml,yaws. These are very useful.
You can use the header of the request Accept
to determine what kind of representation the client prefers. This header can be headers
obtained in the record and can be arg
used in the record:
ACCEPT_HDR = (arg#arg.headers) #headers. Accept
If the resource supports multiple appearances, you can check the header to see if the client specifies the type of representation it wants. If the client does not send the accept
Header, the above code accept_hdr
The variable will be set to atom undefined
, your resource can provide any representation it deems best. If accept
header is not empty, the service can parse accept_hdr
variables to determine which resources are sent. If the resource fails to meet the client's request, the service returns the HTTP status code 406
, which means "not acceptable", Also returns a
case Accept_hdr of
undefined->
% return default representation;
"Application/xml"->
% return XML representation;
"Application/json"->
% return JSON representation;?
_other->
Msg = "Accept:application/xml, Application/json",
Error = "Error 406",
[{status, 406},
{header, {content_type, ' text/html '}},
{ehtml,
[{head, [], [{title, [], error}]},
{body, [],
[{h1, [], error},
{p, [], MSG}]}]
End.
The above Erlang code first checks Accept_hdr
the value to determine whether application/xml
or not application/json
. If it is one of the two, the resource will return an appropriate representation; if not, the code will return an HTTP status code 406
, along with an HTML document indicating the type of imagery the resource can support.
Another way to handle the expected representation is (as you've guessed) adding it as another parameter to the out
function. With this approach, Erlang pattern matching ensures that our requests can be forwarded to the correct function, which will be included in the request URI/method/representation
. This avoids the clutter of handlers that result from case statements like the above.
Incidentally, this example also shows the type of Yaws ehtml
, which is one of a series of Erlang terms that represents the way HTML behaves. I find it ehtml
quite natural to use it because it is directly behind an HTML structure, but it is more compact and you avoid the tedious and error of many matching tags when you write HTML semantics.
Status code
RESTful Web services must return a correct HTTP status code, which is specified by RFC 2616. Using Yaws can easily return to the correct state: Just out/1
include a status tuple in the result of the function. If your code does not explicitly set the state, Yaws will set a 200 status for you, indicating success.
HTTP Header
Yaws can also easily get the request header and set the reply header. We've seen an example of getting headers from a scratch record Accept
, and getting the other request headers is exactly the same way. Setting the reply header only needs to place a header tuple in the reply, as follows:
{header, {content_type, ' text/html '}}
The above code will Content-type
set the header to "text/html". Similarly, in the previous example, we returned a 405 status indicating "Method not allowed" error, and we should also include the following header:
Is it appmod, or is it Yapp?
So far, we've seen how yaws and Erlang can easily address some of the key issues that need to be faced in restful web services. There is another question, should we choose Appmod, or Yapp? The answer depends on what your service is going to do. If you write a service that must interact with other backend services, then Yapp may be the best choice. Because they are downright ERLANG/OTP applications, they usually have initialization and finalization functions that are used to create and close connections to the backend. For example, if your Yapp is a ERLANG/OTP gen_server, your INIT/1 function can create gen_server
the state that the framework provides to you and allow you to modify it. Called every time an external request is received from the server init/1
. In addition, using Yapp can also use appmod, so choosing between the two is not very critical. Finally, Yapps can be added to the ERLANG/OTP tree, which monitors yapp programs and restarts them once they fail. The governance tree plays an important role in the long and stable operation of the Erlang system.
This article is tailored for restful Web services based on backend rather than relational databases. If you are writing a traditional, relational database-based Web service, you should try out the Erlyweb for this type of Web service, which is also based on Yaws and Erlang.
Conclusion
Another important aspect of writing RESTful Web services is choosing the right programming language. Over the years, the various service frameworks developed in different programming languages have been dizzying, and most are quickly disappearing from the perspective of people because they do not solve real problems very well. Yaws and Erlang are not designed to provide a framework for restful services, but they provide more functionality than many other languages that develop dedicated rest-specific frameworks for this area of development.
While this article will inevitably not delve into the details of Yaws, Erlang, and restful web services, hopefully it will involve important topics and provide a way to solve these problems with minimal code. In my experience, building Web applications using Yaws and Erlang is simple, and the final code is easy to read, maintain, and extend.
About the author
Steve Vinoski is a member of IEEE and ACM. Over the past 20 years, he has authored more than 80 articles, columns, and monographs on distributed computing and integration, alone or in collaboration with others, and for the past 6 years he has been responsible for the "Toward Integration" column of IEEE Internet Computing magazine. You can send him an email [email protected], or visit his blog:http://steve.vinoski.net/blog/.
View the original English text : RESTful Services with Erlang and Yaws
From: Http://www.infoq.com/cn/articles/vinoski-erlang-rest
Develop restful services using Erlang and Yaws