• Building A Node.js Express API To Convert Markdown To HTML
  • By Sameer Borate
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: Baddyo
  • Proofread by: Fireairforce, JackEggie

Learn how to create interface endpoints using node.js and Express frameworks by building an application that converts Markdown syntax to HTML.

Markdown is a lightweight text markup language that converts tagged text into a variety of formats. Markdown was invented to allow people to “write in plain text in an easy-to-read and easy-to-write format” that could be converted to valid XHTML (or HTML) on demand. Currently, the Markdown syntax is becoming more and more popular with WordPress support.

The purpose of this article is to show you how to create interface endpoints using the Node.js and Express frameworks. We’ll build an application that converts Markdown to HTML, and learn about Node.js and Express along the way. We will also add validation to the interface to prevent abuse of our application.

A Markdown application based on Node.js

We call this neat little application the “Markdown Converter,” and we upload the text from the Markdown syntax to it to get the HTML version. The application is implemented using the Node.js framework Express and supports validation of transformation requests.

We’ll implement the application in pieces — creating a basic framework with Express and then adding features like validation mechanisms. So let’s start building the basics!

Phase 1: Initialize Express

Assuming you already have Node.js installed in your operating system, let’s create a folder (let’s call it “markdown-api”) to store our code and go to that folder:

$ mkdir markdown-api
$ cd markdown-api
Copy the code

Use the NPM init command to create a package.json file. This command prompts you for information such as app name and version.

For this exercise, you just press Enter and use the default information. I use index.js as the default entry file, but you can set it to app.js or whatever you like.

Now let’s install Express in the markdown-api directory and add it to the list of dependencies:

$ npm install express --save
Copy the code

Create an index.js file in the current directory (markdown-api) and add the following code to test whether the Express framework is installed successfully:

const express = require('express');
var app = express();
 
app.get('/'.function(req, res){
    res.send('Hello World! ');
});
 
app.listen(3000);
Copy the code

Visit http://localhost:3000 to see if the test file runs successfully. If all goes well, we’ll see “Hello World!” in the browser. “, then you can build the basic interface for Markdown to HTML.

Phase 2: Build the basic interface

The main purpose of this interface is to convert Markdown to HTML. It will have two endpoints:

  • /login
  • /convert

The login endpoint is used to validate valid requests; The convert endpoint is used to convert Markdown to HTML.

Here is the basic interface code to invoke both endpoints. Calling Login returns a “Authenticated” string, while calling Convert returns the Markdown text you uploaded. The main method simply returns a “Hello World!” A string.

const express = require("express");
const bodyParser = require('body-parser');
    
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
 
app.get('/'.function(req, res){
    res.send('Hello World! ');
});
 
app.post('/login'.function(req, res) {
    res.send("Authenticated"); }); app.post("/convert".function(req, res, next) {
    console.log(req.body);
    if(typeof req.body.content == 'undefined' || req.body.content == null) {
        res.json(["error"."No data found"]);
    } else {
        res.json(["markdown", req.body.content]); }}); app.listen(3000.function() {
 console.log("Server running on port 3000");
});
Copy the code

We use the middleware body-Parser to assist in parsing incoming requests. The middleware puts the parsing results in the req.body property for your use. It’s possible to parse the request without middleware, but that would be too cumbersome.

You can install body-parser with NPM:

$ npm install body-parser
Copy the code

Now that everything is ready, we need to test it with Postman. Let’s start with a brief introduction to Postman.

Postman profile

Postman is an interface development tool that makes it extremely easy to build, modify, and test interface endpoints using its Web version or desktop client (the Web version is down). It can generate various types of HTTP requests, such as GET, POST, PUT, and PATCH. Postman supports Windows, macOS, and Linux.

Take a look at Postman:

(High Definition)

To invoke an interface endpoint, you need to follow these steps:

  1. Enter the destination URL in the address bar at the top;
  2. Select HTTP method on the left side of the address bar;
  3. Click the “Send” button.

Postman sends the request to the app, gets the response and displays it in a window at the bottom of the screen. That’s the basic use of Postman. In our application, we also need to add other parameters to the request, which we’ll talk about later.

Use the Postman

After getting familiar with Postman, it’s time to actually use it.

Start the Markdown-api application from the command line:

$ node index.js
Copy the code

To test the basic interface code, we’ll call the interface with Postman. Notice that we use the POST method to pass the text to the application.

Our application receives the text to be transformed through the content parameter of the POST method. We pass it as a URL encoding format. Strings are returned in JSON format — the first field always returns a string markdown, while the second field returns converted text. Then, when we add the Markdown processing code, it returns the converted text.

Phase 3: Add the Markdown transformation code

Now that the basic framework of the application is in place, let’s take a look at the JavaScript library, Which we will use to convert Markdown to HTML. Haggis is implemented in the JavaScript language and supports two-way conversions between Markdown and HTML.

(High Definition)

Install Haggis with NPM:

$ npm install showdown
Copy the code

After adding the required MOresco code, our code should look like this:

const express        = require("express");
const bodyParser = require('body-parser');
const showdown   = require('showdown');
    
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
 
converter = new showdown.Converter();

app.get('/'.function(req, res){
    res.send('Hello World! ');
});
 
app.post('/login'.function(req, res) {
    res.send("Authenticated"); }); app.post("/convert".function(req, res, next) {
    if(typeof req.body.content == 'undefined' || req.body.content == null) {
        res.json(["error"."No data found"]);
    } else {
        text = req.body.content;
        html = converter.makeHtml(text);
        res.json(["markdown", html]); }}); app.listen(3000.function() {
 console.log("Server running on port 3000");
});
Copy the code

The core code for the conversion format is in the /convert endpoint, as shown below. This code will convert the Markdown text you uploaded into HTML and return the result in JSON format.

. }else {
        text = req.body.content;
        html = converter.makeHtml(text);
        res.json(["markdown", html]);
    }
Copy the code

Converter.makeHTML (text) is the method responsible for the transformation. The transformation process can be configured in various ways using the setOption method:

converter.setOption('optionKey'.'value');
Copy the code

For example, you can configure it to automatically insert specific urls without any markup.

converter.setOption('simplifiedAutoLink'.'true');
Copy the code

In Postman’s example, if we set simplifiedAutoLink to true, passing a simple string (such as Google Home http://www.google.com/) would return the following:

<p>Google home <a href="http://www.google.com/">http://www.google.com/</a></p>
Copy the code

Otherwise, to achieve the same effect, we must add the tag information:

Google home <http://www.google.com/>
Copy the code

There are also many configuration items that control the Markdown transformation process. You can find a complete list of configuration items here.

We have now implemented a “converter” endpoint that converts Markdown to HTML. Let’s go further and add validation.

Phase 4: Implement interface authentication with Passport

Throwing an interface out to others without adding the proper validation mechanism encourages users to use your interface unrestricted. This will invite some unscrupulous person to abuse the interface, and the flood of requests will wear down your server. To avoid this situation, we must add the appropriate validation mechanism to the interface.

We will use the Passport package to implement the authentication mechanism. Like the body-Parser middleware used earlier, Passport is a Node.js based validation middleware. The reason for using it is that it supports a variety of authentication mechanisms (user name and password authentication, Facebook account authentication, Twitter account authentication, etc.) so that we can choose the authentication method flexibly. Adding the Passport middleware is simple without much code change.

Install Passport with NPM:

$ npm install passport
Copy the code

We also use the local policy for validation, which I’ll explain in more detail later. So install passport- Local as well.

$ npm install passport-local
Copy the code

You’ll also need the encoding/decoding module JWT (JSON Web Token) :

$ npm install jwt-simple
Copy the code

Policy in Passport

The Passport middleware uses the concept of policies to validate requests. A policy is a set of methods that help you verify a variety of requests, from simple username and password authentication to open authorization (Facebook or Twitter account authentication) to OpenID authentication. The authentication policy used by an application needs to be pre-configured to validate requests.

In our own applications, we will use a simple user name and password authentication scheme that is easy to understand and code. Currently, Passport supports more than 300 authentication policies.

While the Passport’s design is complex, its use is simple. The following example shows how validation can be added to the /convert endpoint. As you can see, it’s easy.

app.post("/convert", 
         passport.authenticate('local', {session: false.failWithError: true }), 
         function(req, res, next) {
        // If this function is called, validation is successful.
        // The request content is empty or not.
        if(typeof req.body.content == 'undefined' || req.body.content == null) {
            res.json(["error"."No data found"]);
        } else {
            text = req.body.content;
            html = converter.makeHtml(text);
            res.json(["markdown", html]);
        }}, 
        // When the authentication fails, "Unauthorized" is returned
        function(err, req, res, next) {
            return res.status(401).send({ success: false.message: err })
        });
Copy the code

Now, in addition to the Markdown string to be converted, we will also send the username and password for verification against the application’s username and password. Because we are using a local authentication policy, the authentication credentials are stored in the code itself.

This may seem like a crude way to verify, but it’s good enough for a demo level application. Simple examples also help us understand the validation process. By the way, a common security measure is to store credentials in environment variables. Of course, a lot of people don’t like this approach, but I think it’s a relatively safe approach.

A complete example of the validation function is as follows:

const express = require("express");
const showdown  = require('showdown');
const bodyParser = require('body-parser');
const passport = require('passport');
const jwt = require('jwt-simple');
const LocalStrategy = require('passport-local').Strategy;
 
    
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
 
converter = new showdown.Converter();
 
const ADMIN = 'admin';
const ADMIN_PASSWORD = 'smagazine';
const SECRET = 'secret#4456';
 
passport.use(new LocalStrategy(function(username, password, done) {
  if (username === ADMIN && password === ADMIN_PASSWORD) {
    done(null, jwt.encode({ username }, SECRET));
    return;
  }
  done(null.false);
}));
 
app.get('/'.function(req, res){
    res.send('Hello World! ');
});
 
 
app.post('/login', passport.authenticate('local', {session: false }),
                function(req, res) {
                // If this function is called, validation is successful.
                // Return "Authenticated".
                res.send("Authenticated");
  });
  
 
app.post("/convert", 
         passport.authenticate('local', {session: false.failWithError: true }), 
         function(req, res, next) {
        // If this function is called, validation is successful.
        // The request content is empty or not.
        if(typeof req.body.content == 'undefined' || req.body.content == null) {
            res.json(["error"."No data found"]);
        } else {
            text = req.body.content;
            html = converter.makeHtml(text);
            res.json(["markdown", html]);
        }}, 
        // When the authentication fails, "Unauthorized" is returned
        function(err, req, res, next) {
            return res.status(401).send({ success: false.message: err })
        });
 
 
app.listen(3000.function() {
 console.log("Server running on port 3000");
});
Copy the code

A Postman session with validation looks like this:

Test the final application with Postman

As you can see here, we uploaded a piece of text from the Markdown syntax and got the results in the properly converted HTML version. We only tested a single line of text, but the interface has the ability to convert large chunks of text.

That’s our first taste of Node.js and Express — building an interface endpoint. Building an interface is a complex subject, and there are some details that you should know when you want to build an interface, but I’m sorry I can’t do that in this article, but MAYBE in a future article.

Access our interface in other applications

Now that the interface is set up, we can write a little script based on Node.js to prove that the interface works. In this case, we need to install the Request package to make it easy to send HTTP requests. (Most likely you have already installed it)

$ npm install request --save
Copy the code

The code shown below sends a request to our interface and receives a response. As you can see, the request package simplifies the process considerably. The Markdown text to be converted is stored in the textToConvert variable.

Before running the following script, you need to make sure that the interface application is already running. You need to run the script in a separate command window.

Note: In variablestextToConvert“, we use the ‘ ‘symbol to wrap multiple lines of JavaScript code, not single quotes.

var Request = require("request");
 
// Markdown begins the text
var textToConvert = `Heading ======= ## Sub-heading Paragraphs are separated by a blank line. Two spaces at the end of a line produces a line break. Text attributes _italic_, **bold**, 'monospace'. A [link](http://example.com). Horizontal rule:`;
 
// Markdown the end of the text
                    
Request.post({
    "headers": { "content-type": "application/json" },
    "url": "http://localhost:3000/convert"."body": JSON.stringify({
        "content": textToConvert,
        "username": "admin"."password": "smagazine"})},function(error, response, body){
    // Exit when the connection fails.
    if(error) {
        return console.log(error);
    }
    // Display the converted text
    console.dir(JSON.parse(body));
});
Copy the code

When sending a POST request to the interface, we need to provide the Markdown text and credentials to be transformed. If the credentials are incorrect, we will receive an error message.

{
  success: false.message: {
    name: 'AuthenticationError'.message: 'Unauthorized'.status: 401}}Copy the code

For a validated request, the above Markdown sample is converted to the following format:

[ 'markdown',
  `<h1 id="heading">Heading</h1>
  <h2 id="subheading">Sub-heading</h2>
  <p>Paragraphs are separated by a blank line.</p>
  <p>Two spaces at the end of a line<br />
  produces a line break.</p>
  <p>Text attributes <em>italic</em>.<strong>bold</strong>, 'monospace'.
  A <a href="http://example.com">link</a>.
  Horizontal rule:</p>`]Copy the code

In this example, we deliberately write a piece of Markdown text, which can come from a file, a Web form, and more. But the request process is the same.

Note: When we send a request in application/ JSON format, we need to parse the response body in JSON format, so we call the json.stringify function. As you can see, the test or interface application only needs a small example, which will not be covered here.

conclusion

In this article, we’ve organized a tutorial to learn how to build interfaces using the Node.js and Express framework. Instead of aimlessly creating some boring application, it’s useful to build an interface that converts Markdown into HTML. Through this process, we learned to add validation mechanisms to interface endpoints and learned several ways to test applications with Postman.

If you find any errors in the translation or other areas that need improvement, you are welcome to revise and PR the translation in the Gold Translation program, and you can also get corresponding bonus points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.