Skip to content

Instantly share code, notes, and snippets.

@lcrilly
Last active October 16, 2021 13:11
Show Gist options
  • Save lcrilly/c2bd3264842781b339d6452ea102db98 to your computer and use it in GitHub Desktop.
Save lcrilly/c2bd3264842781b339d6452ea102db98 to your computer and use it in GitHub Desktop.
Workshop: Deploying NGINX as an API Gateway

Workshop: Deploying NGINX as an API Gateway

NGINX is the world’s number one API gateway, delivering the vast majority of today’s API traffic, deployed as standalone gateways or embedded in API management products. This workshop is about deploying NGINX as a lightweight API gateway in a way that supports long-term maintenance and can be automated with common DevOps tooling.

In this hands-on workshop, you will configure NGINX to perform the common API gateway functions of request routing, rate limiting, and authentication for multiple APIs. We will also touch on advanced use cases such as HTTP method enforcement, and JSON validation.

Previous experience of NGINX is valuable, but not essential. Technical requirements:

  • Mandatory: laptop with internet connection
  • Highly recommended: clean installation of NGINX (minimum 1.14.0) - limited assistance for this task will be available at the workshop
  • Recommended: command line tools: curl, wget, jq
upstream f1-admin {
zone f1-admin 64k;
server f1-admin.nginxtraining.com:8006;
}
upstream f1-data {
zone f1-data 64k;
server f1-data.nginxtraining.com:9007;
}
# vim: syntax=nginx
client_one:{PLAIN}7b5ziqmrgxmrjtfmka99vcit
client_two:{PLAIN}qzvv6y1emqfbbxofrcwyjs35
client_six:{PLAIN}mgcjh8fv6u9y3bvf9h3ypb9t
server {
listen 8080;
# TLS config goes here (for production use)
include conf.d/my_apis/*.conf;
# Invalid resource
location / {
return 400;
}
# Error responses
proxy_intercept_errors on; # Do not send backend errors to the client
default_type application/json; # If no content-type then assume JSON
error_page 400 = @400;
location @400 {
return 400 '{"status":400,"message":"Bad request"}\n';
}
}
limit_req_zone $remote_addr zone=perip:1m rate=2r/s;
# vim: syntax=nginx
error_page 400 = @400;
location @400 { return 400 '{"status":400,"message":"Bad request"}\n'; }
error_page 401 = @401;
location @401 { return 401 '{"status":401,"message":"Unauthorized"}\n'; }
error_page 403 = @403;
location @403 { return 403 '{"status":403,"message":"Forbidden"}\n'; }
error_page 404 = @404;
location @404 { return 404 '{"status":404,"message":"Resource not found"}\n'; }
error_page 405 = @405;
location @405 { return 405 '{"status":405,"message":"Method not allowed"}\n'; }
error_page 408 = @408;
location @408 { return 408 '{"status":408,"message":"Request timeout"}\n'; }
error_page 413 = @413;
location @413 { return 413 '{"status":413,"message":"Payload too large"}\n'; }
error_page 414 = @414;
location @414 { return 414 '{"status":414,"message":"Request URI too large"}\n'; }
error_page 415 = @415;
location @415 { return 415 '{"status":415,"message":"Unsupported media type"}\n'; }
error_page 426 = @426;
location @426 { return 426 '{"status":426,"message":"HTTP request was sent to HTTPS port"}\n'; }
error_page 429 = @429;
location @429 { return 429 '{"status":429,"message":"API rate limit exceeded"}\n'; }
error_page 495 = @495;
location @495 { return 495 '{"status":495,"message":"Client certificate authentication error"}\n'; }
error_page 496 = @496;
location @496 { return 496 '{"status":496,"message":"Client certificate not presented"}\n'; }
error_page 497 = @497;
location @497 { return 497 '{"status":497,"message":"HTTP request was sent to mutual TLS port"}\n'; }
error_page 500 = @500;
location @500 { return 500 '{"status":500,"message":"Server error"}\n'; }
error_page 501 = @501;
location @501 { return 501 '{"status":501,"message":"Not implemented"}\n'; }
error_page 502 = @502;
location @502 { return 502 '{"status":502,"message":"Bad gateway"}\n'; }
# vim: syntax=nginx
location /api/f1/ {
auth_basic "F1";
auth_basic_user_file conf.d/api_clients.htpasswd;
limit_req zone=perip;
limit_req_status 429;
location = /api/f1/seasons {
limit_except GET POST { deny all; }
proxy_pass http://f1-admin;
}
location ~ /api/f1/[12][0-9]+ {
proxy_pass http://f1-data;
}
location /api/f1/drivers {
proxy_pass http://f1-data;
}
}
# vim: syntax=nginx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment