Всё о web

Для чайников и не только


Создаём API сервер на expressjs + websockets Часть 1

Декабрь 23, 2016

Привет, дорогие мои котяточки. Сегодня мы быстренько поднимем API сервер на expressjs и веб-сокетах. Как обычно нет времени объяснять зачем мне это нужно, just do it!

Создаём папку с проектом ("api-express" в моём случае), заходим в неё и инициализируем npm пакет:

npm init -f

Открываем вновь созданный package.json, и добавляем немного зависимостей: express и express-ws.

{
  "name": "api-express",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "*",
    "express-ws": "*"
  }
}

Далее делаем npm install, создаём папку js, файл index.js в корне проекта, и файл app.js в папке js.

Содержимое файла index.js

'use strict'

let app = require('./js/app')

Сейчас от него нужно только инициализировать главный объект. А вот в main.js уже создаём наш expressjs сервер:

'use strict'

const express = require('express')
let app = express()
let expressWs = require('express-ws')(app)

app.ws('/', function(ws, req, next) {
  ws.on('message', function(msg) {
    console.log('msg:', msg)
  })
})

app.listen(3000, function() {
  console.log('Started, port: 3000')
})

После этого можем запустить наш сервер:

node index.js

Чтобы проверить, работает ли оно, ставим на гугло-хром плагин "Smart websocket client". Открываем его, вводим адрес ws://localhost:3000 коннектимся. И отправляем любые данные, при этом они должны залогиться в консольке:

Так как в вебсокетах нет http рутов, да и ваще мы получаем просто строку с данными, сам БГ велел использовать json для общения между клиентом и сервером. Но прежде всего давайте напишем небольшую RESTful like документацию на наше api.

1. randomString action

Request:

{
  "get": "randomString",  # Route
  "length": 12345         # stringlength
}

Response:

{
  "code": 200,            # Response code
  "message": "OK",        # Response message
  "data": "abcde"         # Response data
}

2. Error responses

{
  "code" : 12345,             # Error code
  "message" : "Blabla error", # Error message
}

Теперь начинаем воплощать нашу документацию в код. В папке js создаём router.js открываем его и пишем следующий код:

'use strict'

const RandomString = require('./actions/randomString') // Подключаем экшен
const errors = require('./errors')

module.exports = class Router {
  
  constructor() {
    this.randomString = new RandomString()
  }
  
  parseRequest(str) {
    let data = false
    try {
      data = JSON.parse(str)
    } catch(e) {
      
    }
    return data
  }
  
  go(req, ws, msg) {
    let data = this.parseRequest(msg) // Вдруг прилетел неправильный json
    if( data ) {
      switch( data.get ) { 
      case 'randomString': // Смотрим, есть ли у нас экшен
        this.randomString.response(ws, data)
        break
      
      default: // Либо отдаём 404
        ws.send( JSON.stringify(errors['404']) )
        break
      }
    } else 
      ws.send( JSON.stringify(errors['400']) )    
  }
  
}

Тут же создаём errors.js:

'use strict'

let errors = {
  '400': {
    code: 400,
    message: 'Bad Request',
    description: 'Bad request data'
  },
  '401': {
    code: 401,
    message: 'Unauthorized',
    description: 'Please authorize first.'
  },
  '404': {
    code: 404,
    message: 'Not found',
    description: 'Action not found'
  },
  '500': {
    code: 500,
    message: 'Internal Server Error',
    description: 'Internal Server Error.'
  }
}

module.exports = errors

Теперь создаём папку "actions" и в ней randomString.js:

'use strict'

module.exports = class RandomString {
  
 getRandomString(length) {
   let text = ''
   const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'

   for( let i=0; i < length; i++ )
     text += possible.charAt(Math.floor(Math.random() * possible.length))

   return text
  }
  
  response(ws, data) {
    if( data.length )
      ws.send( JSON.stringify({
        code: 200,
        message: 'OK',
        data: this.getRandomString(data.length)
      }) )
    else
      ws.send( JSON.stringify(errors['400']) )
  }
  
}

Нам осталось немного подправить app.js и всё будет готово:

'use strict'

const express = require('express')
const Router = require('./router')

let router = new Router()
let app = express()
let expressWs = require('express-ws')(app)

app.ws('/', function(ws, req, next) {
  ws.on('message', function(msg) {
    router.go(req, ws, msg)
  })
})

app.listen(3000, function() {
  console.log('Started, port: 3000')
})

Проверяем, отправляем неправильный запрос:

Всё нормально, получили в ответ ошибку. Теперь отправляем правильный запрос:

Так же всё ок. В ответ получили код 200 и случайную строку в 12 символов. Заготовка под API сервер готова, теперь можно подключать нормальные экшены.

Архив с проектом: api-express-ws.tar.gz



Комментарии

Оставить комментарий:

Ваш e-mail не будет опубликован. Обязательные поля помечены *