Nginx で HTTP API 化

lua-nginx-module の ngx.socket.tcp() や ngx.socket.udp() を使用すると、
HTTP 以外の TCP や UDP を使用したプロトコルでデータを送受信するようなシステムにも Nginx から直接接続することが可能です

そのため、Nginx の後に別途、HTTP リクエストを受信して、これらのシステムと接続するようなサーバを用意する必要がなくなります


今回は簡単に、POST リクエストで送った path と value を使用して、Graphite (Carbon) に UDP および TCP でデータを送ってみました

## 設定

```ngixn.conf

        location /graphite/udp {
            set $graphite_host '127.0.0.1';
            set $graphite_port 2003;

            content_by_lua '
                local sock = ngx.socket.udp()
                local graphite_host = ngx.var.graphite_host
                local graphite_port = ngx.var.graphite_port
                local ok, err = sock:setpeername(graphite_host, tonumber(graphite_port))
                if not ok then
                    ngx.say(err)
                    return
                end

                ngx.req.read_body()
                local args, err = ngx.req.get_post_args()
                if not args then
                    ngx.say(err)
                    return
                end

                local path = args.path
                local value = args.value

                local timestamp = os.time()
                local data = table.concat({path, value, tostring(timestamp)}, " ")
                local ok, err = sock:send(data)
                if err then
                    ngx.say(err)
                    return
                end

                local ok, err = sock:close()
                if not ok then
                    ngx.say(err)
                    return
                end
            ';
        }

        location /graphite/tcp {
            set $graphite_host '127.0.0.1';
            set $graphite_port 2003;

            content_by_lua '
                local sock = ngx.socket.tcp()
                local graphite_host = ngx.var.graphite_host
                local graphite_port = ngx.var.graphite_port
                local ok, err = sock:connect(graphite_host, tonumber(graphite_port))
                if not ok then
                    ngx.say(err)
                    return
                end

                ngx.req.read_body()
                local args, err = ngx.req.get_post_args()
                if not args then
                    ngx.say(err)
                    return
                end

                local path = args.path
                local value = args.value

                local timestamp = os.time()
                local data = table.concat({path, value, tostring(timestamp)}, " ")
                local ok, err = sock:send(data)
                if err then
                    ngx.say(err)
                    return
                end

                local ok, err = sock:close()
                if not ok then
                    ngx.say(err)
                    return
                end
            ';
        }
```

## 送信

curl でデータを送ってみます

```bash:tcp
$ curl -v -X POST --data "path=nginx.tcp.data&value=`expr $RANDOM % 100`" http://localhost:8080/graphite/tcp
* Hostname was NOT found in DNS cache
*   Trying ::1...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /graphite/tcp HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 28 out of 28 bytes
< HTTP/1.1 200 OK
* Server openresty/1.7.4.1 is not blacklisted
< Server: openresty/1.7.4.1
< Date: Sun, 07 Dec 2014 04:57:12 GMT
< Content-Type: application/octet-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
```

```bash:udp
$ curl -v -X POST --data "path=nginx.udp.data&value=`expr $RANDOM % 100`" http://localhost:8080/graphite/udp
* Hostname was NOT found in DNS cache
*   Trying ::1...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /graphite/udp HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 28 out of 28 bytes
< HTTP/1.1 200 OK
* Server openresty/1.7.4.1 is not blacklisted
< Server: openresty/1.7.4.1
< Date: Sun, 07 Dec 2014 04:57:20 GMT
< Content-Type: application/octet-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
```


### Graphite

送られてきたデータをグラフで確認してみます

![スクリーンショット 2014-12-07 13.58.34.png](https://qiita-image-store.s3.amazonaws.com/0/36202/8db4734b-5b12-6d12-69af-e5407ee21838.png)


## 参考 URL

- [HttpLuaModule - Nginx Community](http://wiki.nginx.org/HttpLuaModule)