2021-08-27 12:15:22 +00:00
|
|
|
include /etc/nginx/conf.d/include/proxy-buffer;
|
|
|
|
include /etc/nginx/conf.d/include/proxy-pass-internal;
|
2021-12-23 14:09:54 +00:00
|
|
|
include /etc/nginx/conf.d/include/portal-access-check;
|
2021-08-27 12:15:22 +00:00
|
|
|
|
|
|
|
# variable definititions - we need to define a variable to be able to access it in lua by ngx.var.something
|
2022-03-04 17:48:36 +00:00
|
|
|
set $skylink ''; # placeholder for the base64 skylink
|
|
|
|
set $skylink_base32 ''; # placeholder for the base32 skylink
|
2021-08-27 12:15:22 +00:00
|
|
|
|
|
|
|
# resolve handshake domain by requesting to /hnsres endpoint and assign correct values to $skylink and $rest
|
2021-12-23 14:09:54 +00:00
|
|
|
rewrite_by_lua_block {
|
2021-08-27 12:15:22 +00:00
|
|
|
local json = require('cjson')
|
|
|
|
local httpc = require("resty.http").new()
|
|
|
|
|
|
|
|
-- make a get request to /hnsres endpoint with the domain name from request_uri
|
|
|
|
-- 10.10.10.50 points to handshake-api service (alias not available when using resty-http)
|
|
|
|
local hnsres_res, hnsres_err = httpc:request_uri("http://10.10.10.50:3100/hnsres/" .. ngx.var.hns_domain)
|
|
|
|
|
|
|
|
-- print error and exit with 500 or exit with response if status is not 200
|
|
|
|
if hnsres_err or (hnsres_res and hnsres_res.status ~= ngx.HTTP_OK) then
|
|
|
|
ngx.status = (hnsres_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or hnsres_res.status
|
|
|
|
ngx.header["content-type"] = "text/plain"
|
|
|
|
ngx.say(hnsres_err or hnsres_res.body)
|
|
|
|
return ngx.exit(ngx.status)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- since /hnsres endpoint response is a json, we need to decode it before we access it
|
|
|
|
-- example response: '{"skylink":"sia://XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"}'
|
|
|
|
local hnsres_json = json.decode(hnsres_res.body)
|
|
|
|
|
|
|
|
-- define local variable containing rest of the skylink if provided
|
|
|
|
local skylink_rest
|
|
|
|
|
|
|
|
if hnsres_json.skylink then
|
|
|
|
-- try to match the skylink with sia:// prefix
|
|
|
|
skylink, skylink_rest = string.match(hnsres_json.skylink, "sia://([^/?]+)(.*)")
|
|
|
|
|
|
|
|
-- in case the skylink did not match, assume that there is no sia:// prefix and try to match again
|
|
|
|
if skylink == nil then
|
|
|
|
skylink, skylink_rest = string.match(hnsres_json.skylink, "/?([^/?]+)(.*)")
|
|
|
|
end
|
|
|
|
elseif hnsres_json.registry then
|
|
|
|
local publickey = hnsres_json.registry.publickey
|
|
|
|
local datakey = hnsres_json.registry.datakey
|
|
|
|
|
|
|
|
-- make a get request to /skynet/registry endpoint with the credentials from text record
|
|
|
|
-- 10.10.10.10 points to sia service (alias not available when using resty-http)
|
|
|
|
local registry_res, registry_err = httpc:request_uri("http://10.10.10.10:9980/skynet/registry?publickey=" .. publickey .. "&datakey=" .. datakey, {
|
|
|
|
headers = { ["User-Agent"] = "Sia-Agent" }
|
|
|
|
})
|
|
|
|
|
|
|
|
-- print error and exit with 500 or exit with response if status is not 200
|
|
|
|
if registry_err or (registry_res and registry_res.status ~= ngx.HTTP_OK) then
|
|
|
|
ngx.status = (registry_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or registry_res.status
|
|
|
|
ngx.header["content-type"] = "text/plain"
|
|
|
|
ngx.say(registry_err or registry_res.body)
|
|
|
|
return ngx.exit(ngx.status)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- since /skynet/registry endpoint response is a json, we need to decode it before we access it
|
|
|
|
local registry_json = json.decode(registry_res.body)
|
|
|
|
-- response will contain a hex encoded skylink, we need to decode it
|
|
|
|
local data = (registry_json.data:gsub('..', function (cc)
|
|
|
|
return string.char(tonumber(cc, 16))
|
|
|
|
end))
|
|
|
|
|
|
|
|
skylink = data
|
|
|
|
end
|
|
|
|
|
|
|
|
-- fail with a generic 404 if skylink has not been extracted from a valid /hnsres response for some reason
|
|
|
|
if not skylink then
|
|
|
|
return ngx.exit(ngx.HTTP_NOT_FOUND)
|
|
|
|
end
|
|
|
|
|
|
|
|
ngx.var.skylink = skylink
|
|
|
|
if ngx.var.path == "/" and skylink_rest ~= nil and skylink_rest ~= "" and skylink_rest ~= "/" then
|
|
|
|
ngx.var.path = skylink_rest
|
|
|
|
end
|
2022-03-04 17:48:36 +00:00
|
|
|
|
|
|
|
-- assign base32 skylink to be used in proxy_pass
|
|
|
|
ngx.var.skylink_base32 = require("skynet.skylink").base32(ngx.var.skylink)
|
2021-08-27 12:15:22 +00:00
|
|
|
}
|
|
|
|
|
2022-03-04 17:48:36 +00:00
|
|
|
proxy_set_header Host $skylink_base32.$skynet_portal_domain;
|
|
|
|
proxy_pass $scheme://$server_addr$path$is_args$args;
|
2021-08-27 12:15:22 +00:00
|
|
|
|
|
|
|
# in case siad returns location header, we need to replace the skylink with the domain name
|
|
|
|
header_filter_by_lua_block {
|
2022-02-25 14:24:09 +00:00
|
|
|
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain
|
|
|
|
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain
|
2021-08-27 12:15:22 +00:00
|
|
|
|
|
|
|
if ngx.header.location then
|
|
|
|
-- match location redirect part after the skylink
|
|
|
|
local path = string.match(ngx.header.location, "[^/?]+(.*)");
|
|
|
|
|
|
|
|
-- because siad will set the location header to ie. XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg/index.html
|
|
|
|
-- we need to replace the skylink with the domain_name so we are not redirected to skylink
|
|
|
|
ngx.header.location = ngx.var.hns_domain .. path
|
|
|
|
end
|
|
|
|
}
|