SlideShare ist ein Scribd-Unternehmen logo
1 von 16
Implementing a Fileserver
with Nginx and Lua
techtalk@ferret
Andrii Gakhov
27.02.2017
Current Architecture
Restful API server that communicates with clients using
application/json
Every client is authenticated by a dedicated 3rd party
authentication server and authorized by the API server
End users get benefits from the API via client-side
frontend application
The Problem
At some point, end users request the ability to manage files
using the same client-side application and, consequently,
same API.
allow to process multipart/form-data requests (that will be
proxied from the form on the client-side application)
extract and handle file metadata
provide file storage and access
The Solution
Obviously, such functionality is out of the scope for the API
and the natural decision is to split it across 2
applications:
API is used for meta file management
Fileserver takes care about actual files upload/download
Instead of using Flask/Django etc., we have decided to
implements such functionality in Nginx with Lua scripting
Nginx and Lua
Nginx is a free, open-source, high-performance HTTP server
and reverse proxy, as well as an IMAP/POP3 proxy server.
Lua is a powerful, efficient, lightweight, embeddable
scripting language. It supports procedural programming,
object-oriented programming, functional programming,
data-driven programming, and data description.
The Lua module for Nginx ngx_http_lua_module embeds Lua into
Nginx and by leveraging Nginx's subrequests, allows the
integration of Lua threads into the Nginx event model.
Nginx and Lua
Nginx object is available in Lua as ngx and server variables
are accessible as ngx.var.{name}, requested GET arguments -
as ngx.var.arg_{name}, but unfortunately POST variables Nginx
doesn't parse into variables automatically.
The various *_by_lua_* configuration directives serve as
gateways to the Lua API within the nginx.conf. We use
*_by_lua_block to embed Lua code into Nginx as the most
notable way to do so.
Nginx and Lua
header_filter_by_lua_block - uses Lua code to define an
output header filter (e.g. for overriding or adding a
response header).
access_by_lua_block - acts as an access phase handler and
executes Lua code for every request. as with other access
phase handlers, access_by_lua will not run in subrequests.
content_by_lua_block - acts as a "content handler" and
executes Lua code for every request.
Architecture / Upload
location = /_upload {
limit_except POST { deny all; }
if ($http_content_type !~ "multipart/form-data") {
return 406;
}
lua_need_request_body off;
client_body_buffer_size 200M;
client_max_body_size 200M;
default_type 'application/json';
...
}
Architecture / Download
location ~ ^/_download/(.*)$ {
set $path /$1;
default_type 'application/json';
limit_except GET { deny all; }
...
}
User Authentication
function authenticate_user(access_token)
local params = {
method = ngx.HTTP_GET,
args = {
access_token = access_token
}
}
local res = ngx.location.capture(
"/_auth/access/check", params)
if not res or res.status ~= 200 then
return nil
end
return cjson.decode(res.body)
end
access_by_lua_block {
local cjson = require("cjson")
local access_token = ngx.var.arg_access_token
if not access_token then
return_http_forbidden("Forbidden")
end
-- authenticate user
local credentials = authenticate_user(access_token)
-- if user can't be resolved, return 403 Forbidden
if not credentials or not credentials.data.user.id
then
return_http_forbidden("Forbidden")
end
}
Upload
-- Extract POST variables in a streaming way
-- and store file object in a temporary
-- file (form_data.file.filepath)
-- All.other form variables are in form_data
-- (we expect them to be small)
local helpers = require("utils")
form_data, err = helpers.streaming_multipart_form()
if form_data == nil then
return_http_internal_server_error(err)
end
data = {
status = "not_ready",
title = form.title.value,
filename = form.file.filename,
}
local params = {
method = ngx.HTTP_POST,
args = {access_token = access_token},
body = cjson.encode(data)
}
local res = ngx.location.capture("/_api/v1/file", params)
if not res then
return_http_bad_gateway("No metadata")
end
local create_metadata_resp = res.body
if res and res.status ~= 201 then
ngx.status = res.status
ngx.print(create_metadata_resp)
ngx.exit(res.status)
end
local file_metadata = cjson.decode(create_metadata_resp)
Important part to make it work is to specify
client_body_buffer_size equal to
client_max_body_size.
Otherwise, if the client body is bigger than
client_body_buffer_size, the nginx variable
$request_body will be empty.
Upload
local filex = require("pl.file")
local file_fullpath = "/storage/files/" ..
file_metadata.hash .. file_metadata.path
-- ensure that subdirectories exist (if not, create)
-- store tmp file to its permanent position
is_moved, err = filex.move(
form.file.fullpath, file_fullpath)
-- make it available for download
if is_moved then
local params = {
method = ngx.HTTP_PUT,
args = {access_token = access_token},
body = cjson.encode({status = "ready"})
}
ngx.location.capture(
"/_api/v1/file/" .. file_metadata.id, params)
end
-- provide some headers with metadata
ngx.header["X-File-ID"] = file_metadata.id
ngx.status = ngx.HTTP_CREATED
ngx.print(create_metadata_resp)
ngx.exit(ngx.HTTP_CREATED)
Since we need to manage access to the file, we
use access policy of files’ metadata instead of the
files themselves.
We create metadata in any case (“register the
file”), but allow to download it only if file has status
“ready”, meaning it was successfully created at the
specified location.
Download
local search_by_path = {
filters = {
path = ngx.var.path,
status = "ready"
},
size = 1
}
local params = {
method = ngx.HTTP_POST,
args = {access_token = access_token},
body = cjson.encode(search_by_path)
}
local res = ngx.location.capture(
"/_api/v1/search/files", params)
if not res then
return_http_bad_gateway("Search error")
end
local found = cjson.decode(res.body)
if found.total < 1 then
return_http_not_found("File Not Found")
end
local file_metadata = found.results[1]
ngx.header["X-File-Name"] = file_metadata.name
ngx.header["X-File-Path"] = file_metadata.path
ngx.header["X-File-ID"] = file_metadata.id
ngx.req.set_uri(
"/" .. file_metadata.hash .. file_metadata.path)
ngx.exec("@download_file", download_params)
As soon as the file has been found, its metadata
provides us with all necessary information about
the location and we are ready to respond it to the
user.
Sometimes people recommend to read such file in
Lua and return it to the user with ngx.print that is a
bad idea for big files (Lua virtual machine will just
crash).
Download
location @download_file {
internal;
root /storage/files/;
try_files $uri =404;
header_filter_by_lua_block {
ngx.header["Cache-Control"] = "no-cache"
ngx.header["Content-Disposition"] = "attachment; filename="" .. ngx.header["X-File-Name"] .. """
}
}
The @download_file location is quite simple, but additionally we want to play with response headers to provide
a real filename for download (on our filesystem all files are stored with unique generated names).
It is an internal named location (to prevent unauthorized access) that just serves requested static files from the
desired directory.
How to Use
Upload
curl -XPOST https://files.example.com/_upload?access_token={SOME_TOKEN} 
--form file=@/tmp/file.pdf
--form title="Example title"
-H "Content-Type: multipart/form-data"
Download
curl -XGET https://files.example.com/_download/723533/2338342189083057604.pdf?access_token={SOME_TOKEN}
Thank you
Read it in the web:
https://www.datacrucis.com/research/implementing-api-based-
fileserver-with-nginx-and-lua.html

Weitere Àhnliche Inhalte

Was ist angesagt?

Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog
 Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog
Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDogRedis Labs
 
Build and Manage Multi-Cloud Applications Using Kuma
Build and Manage Multi-Cloud Applications Using KumaBuild and Manage Multi-Cloud Applications Using Kuma
Build and Manage Multi-Cloud Applications Using KumaSven Bernhardt
 
Threat Modeling for Dummies
Threat Modeling for DummiesThreat Modeling for Dummies
Threat Modeling for DummiesAdam Englander
 
Getting Started with Apache Spark on Kubernetes
Getting Started with Apache Spark on KubernetesGetting Started with Apache Spark on Kubernetes
Getting Started with Apache Spark on KubernetesDatabricks
 
Chapter 1: Overview of Network Security
Chapter 1: Overview of Network SecurityChapter 1: Overview of Network Security
Chapter 1: Overview of Network SecurityShafaan Khaliq Bhatti
 
Pen Testing Explained
Pen Testing ExplainedPen Testing Explained
Pen Testing ExplainedRand W. Hirt
 
Actor Patterns and NATS - Boulder Meetup
Actor Patterns and NATS - Boulder MeetupActor Patterns and NATS - Boulder Meetup
Actor Patterns and NATS - Boulder MeetupNATS
 
IPsec on Mikrotik
IPsec on MikrotikIPsec on Mikrotik
IPsec on MikrotikGLC Networks
 
Replacing and Augmenting F5 BIG-IP with NGINX Plus
Replacing and Augmenting F5 BIG-IP with NGINX PlusReplacing and Augmenting F5 BIG-IP with NGINX Plus
Replacing and Augmenting F5 BIG-IP with NGINX PlusNGINX, Inc.
 
NGINX: Basics and Best Practices EMEA
NGINX: Basics and Best Practices EMEANGINX: Basics and Best Practices EMEA
NGINX: Basics and Best Practices EMEANGINX, Inc.
 
Google Cloud Forensics & Incident Response
Google Cloud Forensics & Incident ResponseGoogle Cloud Forensics & Incident Response
Google Cloud Forensics & Incident ResponseChristopher Doman
 
Advanced Flink Training - Design patterns for streaming applications
Advanced Flink Training - Design patterns for streaming applicationsAdvanced Flink Training - Design patterns for streaming applications
Advanced Flink Training - Design patterns for streaming applicationsAljoscha Krettek
 
RethinkConn 2022!
RethinkConn 2022!RethinkConn 2022!
RethinkConn 2022!NATS
 
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개OpenStack Korea Community
 
Process injection - Malware style
Process injection - Malware styleProcess injection - Malware style
Process injection - Malware styleSander Demeester
 
Wireshark
WiresharkWireshark
WiresharkSourav Roy
 
Using ClickHouse for Experimentation
Using ClickHouse for ExperimentationUsing ClickHouse for Experimentation
Using ClickHouse for ExperimentationGleb Kanterov
 
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CT
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CTPalestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CT
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CTTenchi Security
 
Understanding Cyber Attack - Cyber Kill Chain.pdf
Understanding Cyber Attack - Cyber Kill Chain.pdfUnderstanding Cyber Attack - Cyber Kill Chain.pdf
Understanding Cyber Attack - Cyber Kill Chain.pdfslametarrokhim1
 

Was ist angesagt? (20)

Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog
 Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog
Monitoring and Scaling Redis at DataDog - Ilan Rabinovitch, DataDog
 
Build and Manage Multi-Cloud Applications Using Kuma
Build and Manage Multi-Cloud Applications Using KumaBuild and Manage Multi-Cloud Applications Using Kuma
Build and Manage Multi-Cloud Applications Using Kuma
 
Threat Modeling for Dummies
Threat Modeling for DummiesThreat Modeling for Dummies
Threat Modeling for Dummies
 
Getting Started with Apache Spark on Kubernetes
Getting Started with Apache Spark on KubernetesGetting Started with Apache Spark on Kubernetes
Getting Started with Apache Spark on Kubernetes
 
Chapter 1: Overview of Network Security
Chapter 1: Overview of Network SecurityChapter 1: Overview of Network Security
Chapter 1: Overview of Network Security
 
Pen Testing Explained
Pen Testing ExplainedPen Testing Explained
Pen Testing Explained
 
Actor Patterns and NATS - Boulder Meetup
Actor Patterns and NATS - Boulder MeetupActor Patterns and NATS - Boulder Meetup
Actor Patterns and NATS - Boulder Meetup
 
IPsec on Mikrotik
IPsec on MikrotikIPsec on Mikrotik
IPsec on Mikrotik
 
NMAP - The Network Scanner
NMAP - The Network ScannerNMAP - The Network Scanner
NMAP - The Network Scanner
 
Replacing and Augmenting F5 BIG-IP with NGINX Plus
Replacing and Augmenting F5 BIG-IP with NGINX PlusReplacing and Augmenting F5 BIG-IP with NGINX Plus
Replacing and Augmenting F5 BIG-IP with NGINX Plus
 
NGINX: Basics and Best Practices EMEA
NGINX: Basics and Best Practices EMEANGINX: Basics and Best Practices EMEA
NGINX: Basics and Best Practices EMEA
 
Google Cloud Forensics & Incident Response
Google Cloud Forensics & Incident ResponseGoogle Cloud Forensics & Incident Response
Google Cloud Forensics & Incident Response
 
Advanced Flink Training - Design patterns for streaming applications
Advanced Flink Training - Design patterns for streaming applicationsAdvanced Flink Training - Design patterns for streaming applications
Advanced Flink Training - Design patterns for streaming applications
 
RethinkConn 2022!
RethinkConn 2022!RethinkConn 2022!
RethinkConn 2022!
 
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개
[OpenStack Days Korea 2016] Track2 - ì•„ëŠŹìŠ€íƒ€ OpenStack 연동 및 CloudVision ì†”ëŁšì…˜ 소개
 
Process injection - Malware style
Process injection - Malware styleProcess injection - Malware style
Process injection - Malware style
 
Wireshark
WiresharkWireshark
Wireshark
 
Using ClickHouse for Experimentation
Using ClickHouse for ExperimentationUsing ClickHouse for Experimentation
Using ClickHouse for Experimentation
 
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CT
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CTPalestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CT
Palestra Medindo seu nível de Visibilidade e Detecção usando ATT&CK e DeTT&CT
 
Understanding Cyber Attack - Cyber Kill Chain.pdf
Understanding Cyber Attack - Cyber Kill Chain.pdfUnderstanding Cyber Attack - Cyber Kill Chain.pdf
Understanding Cyber Attack - Cyber Kill Chain.pdf
 

Andere mochten auch

Pecha Kucha: Ukrainian Food Traditions
Pecha Kucha: Ukrainian Food TraditionsPecha Kucha: Ukrainian Food Traditions
Pecha Kucha: Ukrainian Food TraditionsAndrii Gakhov
 
Recurrent Neural Networks. Part 1: Theory
Recurrent Neural Networks. Part 1: TheoryRecurrent Neural Networks. Part 1: Theory
Recurrent Neural Networks. Part 1: TheoryAndrii Gakhov
 
Open Source Software You Can Use
Open Source Software You Can UseOpen Source Software You Can Use
Open Source Software You Can UseMaxwell Pearl
 
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…Andrii Gakhov
 
Time series predictions using LSTMs
Time series predictions using LSTMsTime series predictions using LSTMs
Time series predictions using LSTMsSetu Chokshi
 
Bloom filter
Bloom filterBloom filter
Bloom filterfeng lee
 
Probabilistic data structures. Part 3. Frequency
Probabilistic data structures. Part 3. FrequencyProbabilistic data structures. Part 3. Frequency
Probabilistic data structures. Part 3. FrequencyAndrii Gakhov
 
Probabilistic data structures. Part 2. Cardinality
Probabilistic data structures. Part 2. CardinalityProbabilistic data structures. Part 2. Cardinality
Probabilistic data structures. Part 2. CardinalityAndrii Gakhov
 
Probabilistic data structures. Part 4. Similarity
Probabilistic data structures. Part 4. SimilarityProbabilistic data structures. Part 4. Similarity
Probabilistic data structures. Part 4. SimilarityAndrii Gakhov
 
Nginx Conference 2016 - Learnings and State of the Industry
Nginx Conference 2016 - Learnings and State of the IndustryNginx Conference 2016 - Learnings and State of the Industry
Nginx Conference 2016 - Learnings and State of the IndustryBenjamin Scholler
 
Microservices designing deploying
Microservices designing deployingMicroservices designing deploying
Microservices designing deployingSuresh Kumar
 
Machine Learning 101
Machine Learning 101Machine Learning 101
Machine Learning 101Setu Chokshi
 
Trello介çŽč&操䜜èȘȘ明
Trello介çŽč&操䜜èȘȘ明Trello介çŽč&操䜜èȘȘ明
Trello介çŽč&操䜜èȘȘæ˜ŽćŠ€ç’‡ 林
 
skip list
skip listskip list
skip listiammutex
 
Microservices with Spring Cloud
Microservices with Spring CloudMicroservices with Spring Cloud
Microservices with Spring CloudDaniel Eichten
 
New File Server Features Of Windows Server 2008
New File Server Features Of Windows Server 2008New File Server Features Of Windows Server 2008
New File Server Features Of Windows Server 2008Microsoft TechNet
 
Roll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and LuaRoll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and LuaJon Moore
 
Accelerating Your Web Application with NGINX
Accelerating Your Web Application with NGINXAccelerating Your Web Application with NGINX
Accelerating Your Web Application with NGINXKevin Jones
 
Apache Big Data Europe 2015: Selected Talks
Apache Big Data Europe 2015: Selected TalksApache Big Data Europe 2015: Selected Talks
Apache Big Data Europe 2015: Selected TalksAndrii Gakhov
 

Andere mochten auch (20)

Pecha Kucha: Ukrainian Food Traditions
Pecha Kucha: Ukrainian Food TraditionsPecha Kucha: Ukrainian Food Traditions
Pecha Kucha: Ukrainian Food Traditions
 
Recurrent Neural Networks. Part 1: Theory
Recurrent Neural Networks. Part 1: TheoryRecurrent Neural Networks. Part 1: Theory
Recurrent Neural Networks. Part 1: Theory
 
Open Source Software You Can Use
Open Source Software You Can UseOpen Source Software You Can Use
Open Source Software You Can Use
 
14 Skip Lists
14 Skip Lists14 Skip Lists
14 Skip Lists
 
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…
Đ’Đ”Ń€ĐŸŃŃ‚ĐœĐŸŃŃ‚ĐœŃ‹Đ” струĐșтуры ĐŽĐ°ĐœĐœŃ‹Ń…
 
Time series predictions using LSTMs
Time series predictions using LSTMsTime series predictions using LSTMs
Time series predictions using LSTMs
 
Bloom filter
Bloom filterBloom filter
Bloom filter
 
Probabilistic data structures. Part 3. Frequency
Probabilistic data structures. Part 3. FrequencyProbabilistic data structures. Part 3. Frequency
Probabilistic data structures. Part 3. Frequency
 
Probabilistic data structures. Part 2. Cardinality
Probabilistic data structures. Part 2. CardinalityProbabilistic data structures. Part 2. Cardinality
Probabilistic data structures. Part 2. Cardinality
 
Probabilistic data structures. Part 4. Similarity
Probabilistic data structures. Part 4. SimilarityProbabilistic data structures. Part 4. Similarity
Probabilistic data structures. Part 4. Similarity
 
Nginx Conference 2016 - Learnings and State of the Industry
Nginx Conference 2016 - Learnings and State of the IndustryNginx Conference 2016 - Learnings and State of the Industry
Nginx Conference 2016 - Learnings and State of the Industry
 
Microservices designing deploying
Microservices designing deployingMicroservices designing deploying
Microservices designing deploying
 
Machine Learning 101
Machine Learning 101Machine Learning 101
Machine Learning 101
 
Trello介çŽč&操䜜èȘȘ明
Trello介çŽč&操䜜èȘȘ明Trello介çŽč&操䜜èȘȘ明
Trello介çŽč&操䜜èȘȘ明
 
skip list
skip listskip list
skip list
 
Microservices with Spring Cloud
Microservices with Spring CloudMicroservices with Spring Cloud
Microservices with Spring Cloud
 
New File Server Features Of Windows Server 2008
New File Server Features Of Windows Server 2008New File Server Features Of Windows Server 2008
New File Server Features Of Windows Server 2008
 
Roll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and LuaRoll Your Own API Management Platform with nginx and Lua
Roll Your Own API Management Platform with nginx and Lua
 
Accelerating Your Web Application with NGINX
Accelerating Your Web Application with NGINXAccelerating Your Web Application with NGINX
Accelerating Your Web Application with NGINX
 
Apache Big Data Europe 2015: Selected Talks
Apache Big Data Europe 2015: Selected TalksApache Big Data Europe 2015: Selected Talks
Apache Big Data Europe 2015: Selected Talks
 

Ähnlich wie Implementing a Fileserver with Nginx and Lua

nodejs_at_a_glance.ppt
nodejs_at_a_glance.pptnodejs_at_a_glance.ppt
nodejs_at_a_glance.pptWalaSidhom1
 
Language Resource Processing Configuration and Run
Language Resource Processing Configuration and RunLanguage Resource Processing Configuration and Run
Language Resource Processing Configuration and Runmario_munoz
 
Rapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesRapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesciklum_ods
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
Airflow tutorials hands_on
Airflow tutorials hands_onAirflow tutorials hands_on
Airflow tutorials hands_onpko89403
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)PROIDEA
 
Introducing Node.js in an Oracle technology environment (including hands-on)
Introducing Node.js in an Oracle technology environment (including hands-on)Introducing Node.js in an Oracle technology environment (including hands-on)
Introducing Node.js in an Oracle technology environment (including hands-on)Lucas Jellema
 
Local SQLite Database with Node for beginners
Local SQLite Database with Node for beginnersLocal SQLite Database with Node for beginners
Local SQLite Database with Node for beginnersLaurence Svekis ✔
 
Cloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload CourseCloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload Coursecloudbase.io
 
Reverse proxies & Inconsistency
Reverse proxies & InconsistencyReverse proxies & Inconsistency
Reverse proxies & InconsistencyGreenD0g
 
Nginx internals
Nginx internalsNginx internals
Nginx internalsliqiang xu
 
WebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemonWebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemonGeert Van Pamel
 
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...SPTechCon
 
Overview of RESTful web services
Overview of RESTful web servicesOverview of RESTful web services
Overview of RESTful web servicesnbuddharaju
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Dinh Pham
 
Scalable network applications, event-driven - Node JS
Scalable network applications, event-driven - Node JSScalable network applications, event-driven - Node JS
Scalable network applications, event-driven - Node JSCosmin Mereuta
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Baruch Sadogursky
 
Node.js Workshop - Sela SDP 2015
Node.js Workshop  - Sela SDP 2015Node.js Workshop  - Sela SDP 2015
Node.js Workshop - Sela SDP 2015Nir Noy
 

Ähnlich wie Implementing a Fileserver with Nginx and Lua (20)

nodejs_at_a_glance.ppt
nodejs_at_a_glance.pptnodejs_at_a_glance.ppt
nodejs_at_a_glance.ppt
 
Language Resource Processing Configuration and Run
Language Resource Processing Configuration and RunLanguage Resource Processing Configuration and Run
Language Resource Processing Configuration and Run
 
Rapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesRapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devices
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Airflow tutorials hands_on
Airflow tutorials hands_onAirflow tutorials hands_on
Airflow tutorials hands_on
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)
JDD 2017: Nginx + Lua = OpenResty (Marcin StoĆŒek)
 
Introducing Node.js in an Oracle technology environment (including hands-on)
Introducing Node.js in an Oracle technology environment (including hands-on)Introducing Node.js in an Oracle technology environment (including hands-on)
Introducing Node.js in an Oracle technology environment (including hands-on)
 
Local SQLite Database with Node for beginners
Local SQLite Database with Node for beginnersLocal SQLite Database with Node for beginners
Local SQLite Database with Node for beginners
 
Cloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload CourseCloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload Course
 
Frontend Servers and NGINX: What, Where and How
Frontend Servers and NGINX: What, Where and HowFrontend Servers and NGINX: What, Where and How
Frontend Servers and NGINX: What, Where and How
 
Reverse proxies & Inconsistency
Reverse proxies & InconsistencyReverse proxies & Inconsistency
Reverse proxies & Inconsistency
 
Nginx internals
Nginx internalsNginx internals
Nginx internals
 
WebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemonWebTalk - Implementing Web Services with a dedicated Java daemon
WebTalk - Implementing Web Services with a dedicated Java daemon
 
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
 
Overview of RESTful web services
Overview of RESTful web servicesOverview of RESTful web services
Overview of RESTful web services
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
 
Scalable network applications, event-driven - Node JS
Scalable network applications, event-driven - Node JSScalable network applications, event-driven - Node JS
Scalable network applications, event-driven - Node JS
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
 
Node.js Workshop - Sela SDP 2015
Node.js Workshop  - Sela SDP 2015Node.js Workshop  - Sela SDP 2015
Node.js Workshop - Sela SDP 2015
 

Mehr von Andrii Gakhov

Let's start GraphQL: structure, behavior, and architecture
Let's start GraphQL: structure, behavior, and architectureLet's start GraphQL: structure, behavior, and architecture
Let's start GraphQL: structure, behavior, and architectureAndrii Gakhov
 
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...Andrii Gakhov
 
Too Much Data? - Just Sample, Just Hash, ...
Too Much Data? - Just Sample, Just Hash, ...Too Much Data? - Just Sample, Just Hash, ...
Too Much Data? - Just Sample, Just Hash, ...Andrii Gakhov
 
DNS Delegation
DNS DelegationDNS Delegation
DNS DelegationAndrii Gakhov
 
Swagger / Quick Start Guide
Swagger / Quick Start GuideSwagger / Quick Start Guide
Swagger / Quick Start GuideAndrii Gakhov
 
API Days Berlin highlights
API Days Berlin highlightsAPI Days Berlin highlights
API Days Berlin highlightsAndrii Gakhov
 
ELK - What's new and showcases
ELK - What's new and showcasesELK - What's new and showcases
ELK - What's new and showcasesAndrii Gakhov
 
Apache Spark Overview @ ferret
Apache Spark Overview @ ferretApache Spark Overview @ ferret
Apache Spark Overview @ ferretAndrii Gakhov
 
Data Mining - lecture 8 - 2014
Data Mining - lecture 8 - 2014Data Mining - lecture 8 - 2014
Data Mining - lecture 8 - 2014Andrii Gakhov
 
Data Mining - lecture 7 - 2014
Data Mining - lecture 7 - 2014Data Mining - lecture 7 - 2014
Data Mining - lecture 7 - 2014Andrii Gakhov
 
Data Mining - lecture 6 - 2014
Data Mining - lecture 6 - 2014Data Mining - lecture 6 - 2014
Data Mining - lecture 6 - 2014Andrii Gakhov
 
Data Mining - lecture 5 - 2014
Data Mining - lecture 5 - 2014Data Mining - lecture 5 - 2014
Data Mining - lecture 5 - 2014Andrii Gakhov
 
Data Mining - lecture 4 - 2014
Data Mining - lecture 4 - 2014Data Mining - lecture 4 - 2014
Data Mining - lecture 4 - 2014Andrii Gakhov
 
Data Mining - lecture 3 - 2014
Data Mining - lecture 3 - 2014Data Mining - lecture 3 - 2014
Data Mining - lecture 3 - 2014Andrii Gakhov
 
Decision Theory - lecture 1 (introduction)
Decision Theory - lecture 1 (introduction)Decision Theory - lecture 1 (introduction)
Decision Theory - lecture 1 (introduction)Andrii Gakhov
 
Data Mining - lecture 2 - 2014
Data Mining - lecture 2 - 2014Data Mining - lecture 2 - 2014
Data Mining - lecture 2 - 2014Andrii Gakhov
 
Data Mining - lecture 1 - 2014
Data Mining - lecture 1 - 2014Data Mining - lecture 1 - 2014
Data Mining - lecture 1 - 2014Andrii Gakhov
 
Buzzwords 2014 / Overview / part2
Buzzwords 2014 / Overview / part2Buzzwords 2014 / Overview / part2
Buzzwords 2014 / Overview / part2Andrii Gakhov
 
Buzzwords 2014 / Overview / part1
Buzzwords 2014 / Overview / part1Buzzwords 2014 / Overview / part1
Buzzwords 2014 / Overview / part1Andrii Gakhov
 

Mehr von Andrii Gakhov (20)

Let's start GraphQL: structure, behavior, and architecture
Let's start GraphQL: structure, behavior, and architectureLet's start GraphQL: structure, behavior, and architecture
Let's start GraphQL: structure, behavior, and architecture
 
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...
Exceeding Classical: Probabilistic Data Structures in Data Intensive Applicat...
 
Too Much Data? - Just Sample, Just Hash, ...
Too Much Data? - Just Sample, Just Hash, ...Too Much Data? - Just Sample, Just Hash, ...
Too Much Data? - Just Sample, Just Hash, ...
 
DNS Delegation
DNS DelegationDNS Delegation
DNS Delegation
 
Swagger / Quick Start Guide
Swagger / Quick Start GuideSwagger / Quick Start Guide
Swagger / Quick Start Guide
 
API Days Berlin highlights
API Days Berlin highlightsAPI Days Berlin highlights
API Days Berlin highlights
 
ELK - What's new and showcases
ELK - What's new and showcasesELK - What's new and showcases
ELK - What's new and showcases
 
Apache Spark Overview @ ferret
Apache Spark Overview @ ferretApache Spark Overview @ ferret
Apache Spark Overview @ ferret
 
Data Mining - lecture 8 - 2014
Data Mining - lecture 8 - 2014Data Mining - lecture 8 - 2014
Data Mining - lecture 8 - 2014
 
Data Mining - lecture 7 - 2014
Data Mining - lecture 7 - 2014Data Mining - lecture 7 - 2014
Data Mining - lecture 7 - 2014
 
Data Mining - lecture 6 - 2014
Data Mining - lecture 6 - 2014Data Mining - lecture 6 - 2014
Data Mining - lecture 6 - 2014
 
Data Mining - lecture 5 - 2014
Data Mining - lecture 5 - 2014Data Mining - lecture 5 - 2014
Data Mining - lecture 5 - 2014
 
Data Mining - lecture 4 - 2014
Data Mining - lecture 4 - 2014Data Mining - lecture 4 - 2014
Data Mining - lecture 4 - 2014
 
Data Mining - lecture 3 - 2014
Data Mining - lecture 3 - 2014Data Mining - lecture 3 - 2014
Data Mining - lecture 3 - 2014
 
Decision Theory - lecture 1 (introduction)
Decision Theory - lecture 1 (introduction)Decision Theory - lecture 1 (introduction)
Decision Theory - lecture 1 (introduction)
 
Data Mining - lecture 2 - 2014
Data Mining - lecture 2 - 2014Data Mining - lecture 2 - 2014
Data Mining - lecture 2 - 2014
 
Data Mining - lecture 1 - 2014
Data Mining - lecture 1 - 2014Data Mining - lecture 1 - 2014
Data Mining - lecture 1 - 2014
 
Buzzwords 2014 / Overview / part2
Buzzwords 2014 / Overview / part2Buzzwords 2014 / Overview / part2
Buzzwords 2014 / Overview / part2
 
Buzzwords 2014 / Overview / part1
Buzzwords 2014 / Overview / part1Buzzwords 2014 / Overview / part1
Buzzwords 2014 / Overview / part1
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
 

KĂŒrzlich hochgeladen

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...apidays
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbuapidays
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 

KĂŒrzlich hochgeladen (20)

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 

Implementing a Fileserver with Nginx and Lua

  • 1. Implementing a Fileserver with Nginx and Lua techtalk@ferret Andrii Gakhov 27.02.2017
  • 2. Current Architecture Restful API server that communicates with clients using application/json Every client is authenticated by a dedicated 3rd party authentication server and authorized by the API server End users get benefits from the API via client-side frontend application
  • 3. The Problem At some point, end users request the ability to manage files using the same client-side application and, consequently, same API. allow to process multipart/form-data requests (that will be proxied from the form on the client-side application) extract and handle file metadata provide file storage and access
  • 4. The Solution Obviously, such functionality is out of the scope for the API and the natural decision is to split it across 2 applications: API is used for meta file management Fileserver takes care about actual files upload/download Instead of using Flask/Django etc., we have decided to implements such functionality in Nginx with Lua scripting
  • 5. Nginx and Lua Nginx is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. Lua is a powerful, efficient, lightweight, embeddable scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description. The Lua module for Nginx ngx_http_lua_module embeds Lua into Nginx and by leveraging Nginx's subrequests, allows the integration of Lua threads into the Nginx event model.
  • 6. Nginx and Lua Nginx object is available in Lua as ngx and server variables are accessible as ngx.var.{name}, requested GET arguments - as ngx.var.arg_{name}, but unfortunately POST variables Nginx doesn't parse into variables automatically. The various *_by_lua_* configuration directives serve as gateways to the Lua API within the nginx.conf. We use *_by_lua_block to embed Lua code into Nginx as the most notable way to do so.
  • 7. Nginx and Lua header_filter_by_lua_block - uses Lua code to define an output header filter (e.g. for overriding or adding a response header). access_by_lua_block - acts as an access phase handler and executes Lua code for every request. as with other access phase handlers, access_by_lua will not run in subrequests. content_by_lua_block - acts as a "content handler" and executes Lua code for every request.
  • 8. Architecture / Upload location = /_upload { limit_except POST { deny all; } if ($http_content_type !~ "multipart/form-data") { return 406; } lua_need_request_body off; client_body_buffer_size 200M; client_max_body_size 200M; default_type 'application/json'; ... }
  • 9. Architecture / Download location ~ ^/_download/(.*)$ { set $path /$1; default_type 'application/json'; limit_except GET { deny all; } ... }
  • 10. User Authentication function authenticate_user(access_token) local params = { method = ngx.HTTP_GET, args = { access_token = access_token } } local res = ngx.location.capture( "/_auth/access/check", params) if not res or res.status ~= 200 then return nil end return cjson.decode(res.body) end access_by_lua_block { local cjson = require("cjson") local access_token = ngx.var.arg_access_token if not access_token then return_http_forbidden("Forbidden") end -- authenticate user local credentials = authenticate_user(access_token) -- if user can't be resolved, return 403 Forbidden if not credentials or not credentials.data.user.id then return_http_forbidden("Forbidden") end }
  • 11. Upload -- Extract POST variables in a streaming way -- and store file object in a temporary -- file (form_data.file.filepath) -- All.other form variables are in form_data -- (we expect them to be small) local helpers = require("utils") form_data, err = helpers.streaming_multipart_form() if form_data == nil then return_http_internal_server_error(err) end data = { status = "not_ready", title = form.title.value, filename = form.file.filename, } local params = { method = ngx.HTTP_POST, args = {access_token = access_token}, body = cjson.encode(data) } local res = ngx.location.capture("/_api/v1/file", params) if not res then return_http_bad_gateway("No metadata") end local create_metadata_resp = res.body if res and res.status ~= 201 then ngx.status = res.status ngx.print(create_metadata_resp) ngx.exit(res.status) end local file_metadata = cjson.decode(create_metadata_resp) Important part to make it work is to specify client_body_buffer_size equal to client_max_body_size. Otherwise, if the client body is bigger than client_body_buffer_size, the nginx variable $request_body will be empty.
  • 12. Upload local filex = require("pl.file") local file_fullpath = "/storage/files/" .. file_metadata.hash .. file_metadata.path -- ensure that subdirectories exist (if not, create) -- store tmp file to its permanent position is_moved, err = filex.move( form.file.fullpath, file_fullpath) -- make it available for download if is_moved then local params = { method = ngx.HTTP_PUT, args = {access_token = access_token}, body = cjson.encode({status = "ready"}) } ngx.location.capture( "/_api/v1/file/" .. file_metadata.id, params) end -- provide some headers with metadata ngx.header["X-File-ID"] = file_metadata.id ngx.status = ngx.HTTP_CREATED ngx.print(create_metadata_resp) ngx.exit(ngx.HTTP_CREATED) Since we need to manage access to the file, we use access policy of files’ metadata instead of the files themselves. We create metadata in any case (“register the file”), but allow to download it only if file has status “ready”, meaning it was successfully created at the specified location.
  • 13. Download local search_by_path = { filters = { path = ngx.var.path, status = "ready" }, size = 1 } local params = { method = ngx.HTTP_POST, args = {access_token = access_token}, body = cjson.encode(search_by_path) } local res = ngx.location.capture( "/_api/v1/search/files", params) if not res then return_http_bad_gateway("Search error") end local found = cjson.decode(res.body) if found.total < 1 then return_http_not_found("File Not Found") end local file_metadata = found.results[1] ngx.header["X-File-Name"] = file_metadata.name ngx.header["X-File-Path"] = file_metadata.path ngx.header["X-File-ID"] = file_metadata.id ngx.req.set_uri( "/" .. file_metadata.hash .. file_metadata.path) ngx.exec("@download_file", download_params) As soon as the file has been found, its metadata provides us with all necessary information about the location and we are ready to respond it to the user. Sometimes people recommend to read such file in Lua and return it to the user with ngx.print that is a bad idea for big files (Lua virtual machine will just crash).
  • 14. Download location @download_file { internal; root /storage/files/; try_files $uri =404; header_filter_by_lua_block { ngx.header["Cache-Control"] = "no-cache" ngx.header["Content-Disposition"] = "attachment; filename="" .. ngx.header["X-File-Name"] .. """ } } The @download_file location is quite simple, but additionally we want to play with response headers to provide a real filename for download (on our filesystem all files are stored with unique generated names). It is an internal named location (to prevent unauthorized access) that just serves requested static files from the desired directory.
  • 15. How to Use Upload curl -XPOST https://files.example.com/_upload?access_token={SOME_TOKEN} --form file=@/tmp/file.pdf --form title="Example title" -H "Content-Type: multipart/form-data" Download curl -XGET https://files.example.com/_download/723533/2338342189083057604.pdf?access_token={SOME_TOKEN}
  • 16. Thank you Read it in the web: https://www.datacrucis.com/research/implementing-api-based- fileserver-with-nginx-and-lua.html