Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jonasbn/perl-mojolicious-plugin-openapi-tutorial-hello-world
Tutorial for Mojolicious::Plugin::OpenAPI: Hello World
https://github.com/jonasbn/perl-mojolicious-plugin-openapi-tutorial-hello-world
mojolicious openapi perl tutorial
Last synced: about 2 months ago
JSON representation
Tutorial for Mojolicious::Plugin::OpenAPI: Hello World
- Host: GitHub
- URL: https://github.com/jonasbn/perl-mojolicious-plugin-openapi-tutorial-hello-world
- Owner: jonasbn
- License: mit
- Created: 2018-07-26T09:40:14.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-11-04T16:06:54.000Z (about 2 years ago)
- Last Synced: 2023-03-10T19:50:51.451Z (almost 2 years ago)
- Topics: mojolicious, openapi, perl, tutorial
- Language: Shell
- Homepage: https://dev.to/jonasbn/tutorial-mojoliciouspluginopenapi-3jgd
- Size: 77.1 KB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Tutorial on Mojolicious::Plugin::OpenAPI: Hello World
I have always wanted to get my hands _dirty_ with **Swagger**. I recently fell over [Mojolicious::Plugin::OpenAPI](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI), which fits into my [_boring stack_](https://hackernoon.com/the-boring-stack-the-best-way-to-build-interesting-things-9f54420f683e) and I decided to do a prototype.
I followed the [tutorial](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI::Guides::Tutorial) for Mojolicious::Plugin::OpenAPI and found it a bit confusing, so I decided to write up a more simple tutorial.
This tutorial requires that you have [Mojolicious](https://metacpan.org/pod/Mojolicious) installed and recommends [carton](https://metacpan.org/pod/distribution/Carton/script/carton). The installation of these components is however beyond the scope of this tutorial.
**OpenAPI** comes from **Swagger**, which I have had a look at, much water has run under that bridge, so now it is time to look at **OpenAPI** a specification on how to write RESTful APIs in a standardised format.
Here goes, lets start with a basic `hello world` example, [all files are available on GitHub](https://github.com/jonasbn/perl-mojolicious-plugin-openapi-tutorial-hello-world).
## Hello World
First we set up an application, yes we could do a **Mojolicious** lite-app, but I primarily use **Mojolicious** apps, so I think it makes sense to keep stick to this for reference.
```bash
$ mojo generate app HelloWorld
```Jump into our newly generated application directory
```bash
$ cd hello_world
```We then install the plugin we need to enable **OpenAPI** in our **Mojolicious** application
Using **CPAN** shell:
```bash
$ perl -MCPAN -e shell install Mojolicious::Plugin::OpenAPI
```Using `cpanm`:
```bash
$ cpanm Mojolicious::Plugin::OpenAPI
```If you need help installing please refer to [the CPAN installation guide](https://www.cpan.org/modules/INSTALL.html).
Create a definition JSON file based on **OpenAPI** to support an Hello World implementation based on the **OpenAPI** specification:
```bash
$ touch openapi.conf
```The exact name of this file is insignifcant, I just prefer to have clear and understandable filenames for easy identification.
Open `openapi.conf` and insert the following _snippet_:
```json
{
"swagger": "2.0",
"info": { "version": "1.0", "title": "Hello World example" },
"basePath": "/api",
"paths": {
"/hello_world": {
"get": {
"operationId": "helloWorld",
"x-mojo-name": "hello_world",
"x-mojo-to": "example#hello_world",
"summary": "Example app returning hello world",
"responses": {
"200": {
"description": "Returning string 'hello world'",
"schema": {
"type": "object",
"properties": {
"greeting": {
"type": "string"
}
}
}
},
"default": {
"description": "Unexpected error",
"schema": {}
}
}
}
}
}
}
```Now lets go over our definiton.
- `basePath`: defines the root of our URL, so we would be able to access our application at `/api`, recommendations on versioning APIs using this part is do exist, but for our example application, this is out of scope.
- `paths`: here we define our first API path, so our Hello World application can be accessed at: `/api/hello_world`
- `operationId`: the is an operation identifier, it is important for the OpenAPI part, whereas the two following definitions are mappings of the same operation identifier towards the **Mojolicious** application
- `x-mojo-name`: this is the name used to identify our operation in the **Mojolicious** application
- `x-mojo-to`: this is the specification for the route to be used for our operation in the **Mojolicious** application, more on this later
- `responses`: here we define the type we want to handle, for now we settle for `200`. The response definition outline our response, this could be boiled down to a `string` instead of an `object`, with properties, but the example would be come _too simple_ and in my opinion we work primarily with objects over basic types, so this extended example makes for a better reference.
Next step is to enable the [MetaCPAN: Mojolicious::Plugin::OpenAPI](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI) plugin in the application
Open the file: `lib/HelloWorld.pm` and add the following snippet:
```perl
$self->plugin("OpenAPI" => {url => $self->home->rel_file("openapi.json")});
```Note the pointer to our previously created file: `openapi.json`.
The complete file should look like the following:
```perl
package HelloWorld;
use Mojo::Base 'Mojolicious';# This method will run once at server start
sub startup {
my $self = shift;$self->plugin('OpenAPI' => {url => $self->home->rel_file('openapi.json')});
# Load configuration from hash returned by "my_app.conf"
my $config = $self->plugin('Config');# Documentation browser under "/perldoc"
$self->plugin('PODRenderer') if $config->{perldoc};# Router
my $r = $self->routes;# Normal route to controller
$r->get('/')->to('example#welcome');
}1;
```Then we add the actual operation, open the file: `lib/HelloWorld/Controller/Example.pm` and add the following snippet:
```perl
sub hello_world {
my $c = shift->openapi->valid_input or return;my $output = { greeting => 'Hello World' };
$c->render(openapi => $output);
}
```Note that this maps to the definition in our API definition: `openapi.conf`
```json
"x-mojo-to": "example#hello_world",
```The complete file should look like the following:
```perl
package HelloWorld::Controller::Example;
use Mojo::Base 'Mojolicious::Controller';# This action will render a template
sub welcome {
my $self = shift;# Render template "example/welcome.html.ep" with message
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
}sub hello_world {
my $c = shift->openapi->valid_input or return;my $output = { greeting => 'Hello World' };
$c->render(openapi => $output);
}1;
```I decided to implement the tutorial in a scaffolded application, you could create your own controller, but changing an existing controller this way demonstrates how our newly added OpenAPI API end-point, can live in unison with existing and additional end-points.
Now start the application
```bash
$ morbo script/hello_world
```And finally - lets call the API, do note you do not need `jq` and your could use `curl` or `httpie`, so this is just for sticking to the already available tools, `jq` being the exception.
```bash
$ mojo get --verbose http://localhost:3000/api/hello_world | jq
GET /api/hello_world HTTP/1.1
Host: localhost:3000
User-Agent: Mojolicious (Perl)
Content-Length: 0
Accept-Encoding: gzipHTTP/1.1 200 OK
Server: Mojolicious (Perl)
Content-Length: 26
Date: Fri, 27 Jul 2018 08:47:33 GMT
Content-Type: application/json;charset=UTF-8{
"greeting": "Hello World"
}
```Yay! and our first **Mojolicious** **OpenAPI** implementation works!
In addition to the operation, you can obtain the specification by calling the following URL: `/api`
```bash
$ mojo get http://localhost:3000/api/
```And as mentioned earlier our existing operations and parts of the application still works as expected, try calling the URL: `/`
```bash
$ mojo get http://localhost:3000/
```That is it for now, good luck with experimenting with **Mojolicious** **OpenAPI** integration and **OpenAPI**. Thanks to Jan Henning Thorsen ([@jhthorsen](https://twitter.com/jhthorsen)) for the implementation of Mojolicious::Plugin::OpenAPI.
## References
- [MetaCPAN: Mojolicious::Plugin::OpenAPI](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI)
- [MetaCPAN: Mojolicious::Plugin::OpenAPI Tutorial](https://metacpan.org/pod/Mojolicious::Plugin::OpenAPI::Guides::Tutorial)
- [OpenAPI Website](https://www.openapis.org/)
- [GitHub repository for tutorial](https://github.com/jonasbn/perl-mojolicious-plugin-openapi-tutorial-hello-world)