Lua Envoy upstream proxy - nginx

im looking to replace some login logic in on kong, for permission checks on a specific url (like upstream) to an envoy filter in istio.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: api-auth
namespace: api
spec:
workloadLabels:
app: api
filters:
- listenerMatch:
listenerType: SIDECAR_INBOUND
listenerProtocol: HTTP
filterName: envoy.lua
filterType: HTTP
filterConfig:
inlineCode: |
function version()
return "v1"
end
function log(handle, value)
handle:logInfo(version() .. ": " .. value)
end
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
function is_empty(value)
return value == nil or value == ""
end
function get_header(handle, header)
return handle:headers():get(header)
end
function envoy_on_request(request_handle)
local auth_host = "auth-service.services.svc.cluster.local"
local path = "/api/v1/has-permission"
local cluster = "outbound|8080||" .. auth_host
local request_headers = {
[":method"] = "POST",
[":path"] = path,
[":authority"] = auth_host,
["Authorization"] = get_header(request_handle, "Authorization")
}
local request_body = ""
local timeout = 5000 --ms
log(request_handle, "Sending auth request, headers: " .. dump(request_headers) .. ", request_body: " .. request_body .. ", timeout: " .. timeout)
local response_headers, response_body = request_handle:httpCall(
tostring(cluster),
request_headers,
request_body,
timeout
)
log(request_handle, "response_headers: " .. dump(response_headers))
log(request_handle, "response_body: " .. dump(response_body))
if tonumber(response_headers[":status"]) ~= 200 then
log(request_handle, "Key Authentication Failed")
request_handle:respond(
{[":status"] = response_headers[":status"]},
response_body
)
do return end
end
end
so this is my lua, but im still missing something, i need to send extra parameters on my body post request.
example working curl:
curl -i 'https://foo-api.com/list' \
-H 'Connection: keep-alive' \
-H 'Pragma: no-cache' \
-H 'Cache-Control: no-cache' \
-H 'AuthCode: cmdpby50ZWl4ZWlyYUBqdW1pYS5jb20iLCJleHAiOjE1ODUwNDg2MjIsImlzcyI6ImZpcmV3b3JrcyJ9.JkvIhmQuumS32HhSzKuAhpPvjLVwOrRJXwajMjBU9Ag' \
-H 'Accept-Language: en' \
-H 'Authorization: Bearer 6InNlcmdpby50ZWl4ZWlyYUBqdW1pYS5jb20iLCJleHAiOjE1ODUwNDg2MjIsImlzcyI6ImZpcmV3b3JrcyJ9.JkvIhmQuumS32HhSzKuAhpPvjLVwOrRJXwajMjBU9Ag' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Sec-Fetch-Dest: empty' \
-H 'application: COMPANYCODE'
how iam supposed to send this kind of content inside the post using lua?
thanks and best regards

Related

Change project key with bitbucket rest api

I am trying to write a script to move repos in a project to another project but I am getting a 400 error whenever I try.
My python requests line looks like:
url = 'https://bitbucketserver.com/rest/api/1.0/projects/example1/repos/repo1'
token = 'TokenString'
response = requests.put(url, headers={'Content-Type': 'application/json', 'Authorization': 'Bearer' + token}, data={'project': {'key': 'NEW_PROJECT'}}, verify=False)
I get a response 400 that says 'Unexpected character ('p' (code112)): expected a valid value (number, string, array, object, true, false, or null) at [Source: com.atlassian.stash.internal.web.util.web.CountingServletInputStream#7ccd7631; line 1, column 2]
I'm not sure where my syntax is wrong
Not python, but work for me via curl:
curl -u 'USER:PASSWORD' --request PUT \
--url 'https://stash.vsegda.da/rest/api/1.0/projects/OLD_PROJECT/repos/REPO_TO_MOVE' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"project": {"key":"NEW_PROJECT"}
}'
Maybe can someone help.

Post request with form data to login to a website return 400 - Bad request

I am trying to login into this website with below credentials (no worry, it's anonymous):
user = 'MattieBailey#mailinator.com'
password = 'thx9jD3SkrssPKY'
When I logged in manually, I saw in Chrome inspector view there are sequentially a POST request and a GET request.
However, when I tried to simulate these requests with python, I got 400 - Bad request for the POST request. The GET request returned 200 - OK and sent me the content of the login webpage. In the Chrome Inspector View, all these 2 requests returned 302 status code with some response headers contains authorized id_token to use for further requests.
The same result was obtained when I tried to import these two requests to Postman so the problem might not be my code.
My ultimate goal is to get the id_token parameter in the response header of the GET request.
I appreciate your help!
POST request
curl 'https://auth.fiintrade.vn/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DStoxPlus.FiinTrade.SPA%26redirect_uri%3Dhttps%253A%252F%252Ffiintrade.vn%252Fsignin-callback%26response_type%3Did_token%2520token%26scope%3Dopenid%2520FiinTrade.Market%2520FiinTrade.Core%2520FiinTrade.Realtime%2520FiinTrade.Fundamental%26state%3D19e5bb5a7df14a2bab8ded1f265a7bda%26nonce%3D1547e70f8a2940b89dac75565e032046%26clientType%3DWEBCLIENT%26fp%3D54404ac5041ff5b042c29fb397bef44d%26type%3Dredirect' \
-H 'Connection: keep-alive' \
-H 'Cache-Control: max-age=0' \
-H 'sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'Origin: null' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Sec-Fetch-Mode: navigate' \
-H 'Sec-Fetch-User: ?1' \
-H 'Sec-Fetch-Dest: document' \
-H 'Accept-Language: en-US,en;q=0.9,vi;q=0.8' \
-H 'Cookie: _ga=GA1.2...' \
--data-raw 'ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DStoxPlus.FiinTrade.SPA%26redirect_uri%3Dhttps%253A%252F%252Ffiintrade.vn%252Fsignin-callback%26response_type%3Did_token%2520token%26scope%3Dopenid%2520FiinTrade.Market%2520FiinTrade.Core%2520FiinTrade.Realtime%2520FiinTrade.Fundamental%26state%3D19e5bb5a7df14a2bab8ded1f265a7bda%26nonce%3D1547e70f8a2940b89dac75565e032046%26clientType%3DWEBCLIENT%26fp%3D54404ac5041ff5b042c29fb397bef44d%26type%3Dredirect&Username=MattieBailey%40mailinator.com&Password=thx9jD3SkrssPKY&button=login&__RequestVerificationToken=CfDJ8KNrfTjG6sBLmncBE9MMk0dDAX-OFwPXUy1uT0AqrEyhngGIImEM99JGxVKsssw62kRxLY2tHfTqfH8M8Mphqxh80YdwwHM6vpZIb-yVMnma4nS0QCkOf51FMFFu8pPwMM6FY52WEPSWy_ZWuaiAeCU' \
--compressed
GET request
curl 'https://auth.fiintrade.vn/connect/authorize/callback?client_id=StoxPlus.FiinTrade.SPA&redirect_uri=https%3A%2F%2Ffiintrade.vn%2Fsignin-callback&response_type=id_token%20token&scope=openid%20FiinTrade.Market%20FiinTrade.Core%20FiinTrade.Realtime%20FiinTrade.Fundamental&state=19e5bb5a7df14a2bab8ded1f265a7bda&nonce=1547e70f8a2940b89dac75565e032046&clientType=WEBCLIENT&fp=54404ac5041ff5b042c29fb397bef44d&type=redirect' \
-H 'Connection: keep-alive' \
-H 'Cache-Control: max-age=0' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Sec-Fetch-Mode: navigate' \
-H 'Sec-Fetch-User: ?1' \
-H 'Sec-Fetch-Dest: document' \
-H 'sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'Accept-Language: en-US,en;q=0.9,vi;q=0.8' \
-H 'Cookie: _ga=GA1.2...' \
--compressed
Response header that contains id_token
Location: https://fiintrade.vn/signin-callback#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkY4MDA1REIxQkI0MzY4Q0Q3RkJFMUUxRTlEQjkwMTg2MUY5NEFGMTEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiItQUJkc2J0RGFNMV92aDRlbmJrQmhoLVVyeEUifQ.eyJuYmYiOjE2MjkxOTM4MTgsImV4cCI6MTYyOTIyMjYxOCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmZpaW50cmFkZS52biIsImF1ZCI6IlN0b3hQbHVzLkZpaW5UcmFkZS5TUEEiLCJub25jZSI6IjE1NDdlNzBmOGEyOTQwYjg5ZGFjNzU1NjVlMDMyMDQ2IiwiaWF0IjoxNjI5MTkzODE4LCJhdF9oYXNoIjoiOVJNNmdEOWFJZkprdGFCSENHRHpwQSIsInNpZCI6IjQ0MWVkZmM1YTc0MzhhOWNkYzYzYTkwYTM3NmQwOGI1Iiwic3ViIjoiMTcwMzU5IiwiYXV0aF90aW1lIjoxNjI5MTkzODE4LCJpZHAiOiJsb2NhbCIsInVzZXJfaWQiOiIxNzAzNTkiLCJ1c2VyX25hbWUiOiJNYXR0aWVCYWlsZXlAbWFpbGluYXRvci5jb20iLCJuYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6Ik1hdHRpZSIsImZhbWlseV9uYW1lIjoiQmFpbGV5IiwibWlkZGxlX25hbWUiOiIiLCJlbWFpbCI6Ik1hdHRpZUJhaWxleUBtYWlsaW5hdG9yLmNvbSIsInNlcnZpY2VfdHlwZSI6IkZpaW5Hcm91cC5GaWluVHJhZGUiLCJsaXN0X3BhY2thZ2UiOiJGaWluVHJhZGUuVHJpYWwiLCJsaXN0X2ZlYXR1cmUiOiIiLCJsaXN0X2FwaSI6IiIsInJvbGUiOiJDVVNUT01FUiIsImdyb3VwX25hbWUiOiJJbmRpdmlkdWFsIiwic3RhcnRfZGF0ZSI6IjEyLzA4LzIwMjEiLCJlbmRfZGF0ZSI6IjI2LzA4LzIwMjEiLCJoaXRjb3VudF9wZXJtb250aCI6IjAiLCJjb21ncm91cF9saW1pdCI6IiIsInRpY2tlcl9saW1pdCI6IiIsInRpbWVyYW5nZV9saW1pdCI6IjAiLCJkYXRhcmFuZ2VfbGltaXQiOiIwIiwicGVyX21pbnV0ZSI6IjAiLCJwZXJfaG91ciI6IjAiLCJwZXJfZGF5IjoiMCIsInBlcl9tb250aCI6IjAiLCJlbmFibGVkIjoiVHJ1ZSIsImxhc3RfYXR0ZW1wdCI6IjgvMTIvMjAyMSAxMTo1ODoxNyBQTSIsImxhc3RfYXR0ZW1wdF9zdGF0dXMiOiJTVUNDRVNTIiwiZmluZ2VycHJpbnQiOiI1NDQwNGFjNTA0MWZmNWIwNDJjMjlmYjM5N2JlZjQ0ZCIsImNsaWVudHR5cGUiOiJXRUJDTElFTlQiLCJhbXIiOlsicHdkIl19.bObyB2sb-kkAxbxhhLc2hQsEtB6YAvzdtd2OwlLGKrzikqoGPwaQYlA41YK_v9OJLqUPRvKvkSZPBwfbguYXp8KnOAHxyPwM4lrbWc7u_OMIHarANxIsA50ckkj1gEszaGZtN6vtz4QYkxLMdbhHcpTnYd4XidFBVoyMQ3csLFaEifJEVsKfGStqgXW6etIhug5yuPnhjnZbCWdUPh0887auIuB_r7Nc7x6faHLtqr2in8c_TTKoI9YoM6LYBNkB7G7AtYkxlVImbyrdczHqsh6_ajLITuuSKYnwws2STwzPQMrZsIbHo_97ce3AVJcdUzVMXeY343FOYBDZeFteJg&access_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkY4MDA1REIxQkI0MzY4Q0Q3RkJFMUUxRTlEQjkwMTg2MUY5NEFGMTEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiItQUJkc2J0RGFNMV92aDRlbmJrQmhoLVVyeEUifQ.eyJuYmYiOjE2MjkxOTM4MTgsImV4cCI6MTYyOTIyMjQxOCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmZpaW50cmFkZS52biIsImF1ZCI6WyJodHRwczovL2F1dGguZmlpbnRyYWRlLnZuL3Jlc291cmNlcyIsIkZpaW5UcmFkZS5NYXJrZXQiLCJGaWluVHJhZGUuQ29yZSIsIkZpaW5UcmFkZS5SZWFsdGltZSIsIkZpaW5UcmFkZS5GdW5kYW1lbnRhbCJdLCJjbGllbnRfaWQiOiJTdG94UGx1cy5GaWluVHJhZGUuU1BBIiwic3ViIjoiMTcwMzU5IiwiYXV0aF90aW1lIjoxNjI5MTkzODE4LCJpZHAiOiJsb2NhbCIsInVzZXJfaWQiOiIxNzAzNTkiLCJ1c2VyX25hbWUiOiJNYXR0aWVCYWlsZXlAbWFpbGluYXRvci5jb20iLCJuYW1lIjoiIiwiZ2l2ZW5fbmFtZSI6Ik1hdHRpZSIsImZhbWlseV9uYW1lIjoiQmFpbGV5IiwibWlkZGxlX25hbWUiOiIiLCJlbWFpbCI6Ik1hdHRpZUJhaWxleUBtYWlsaW5hdG9yLmNvbSIsInNlcnZpY2VfdHlwZSI6IkZpaW5Hcm91cC5GaWluVHJhZGUiLCJsaXN0X3BhY2thZ2UiOiJGaWluVHJhZGUuVHJpYWwiLCJsaXN0X2ZlYXR1cmUiOiIiLCJsaXN0X2FwaSI6IiIsInJvbGUiOiJDVVNUT01FUiIsImdyb3VwX25hbWUiOiJJbmRpdmlkdWFsIiwic3RhcnRfZGF0ZSI6IjEyLzA4LzIwMjEiLCJlbmRfZGF0ZSI6IjI2LzA4LzIwMjEiLCJoaXRjb3VudF9wZXJtb250aCI6IjAiLCJjb21ncm91cF9saW1pdCI6IiIsInRpY2tlcl9saW1pdCI6IiIsInRpbWVyYW5nZV9saW1pdCI6IjAiLCJkYXRhcmFuZ2VfbGltaXQiOiIwIiwicGVyX21pbnV0ZSI6IjAiLCJwZXJfaG91ciI6IjAiLCJwZXJfZGF5IjoiMCIsInBlcl9tb250aCI6IjAiLCJlbmFibGVkIjoiVHJ1ZSIsImxhc3RfYXR0ZW1wdCI6IjgvMTIvMjAyMSAxMTo1ODoxNyBQTSIsImxhc3RfYXR0ZW1wdF9zdGF0dXMiOiJTVUNDRVNTIiwiZmluZ2VycHJpbnQiOiI1NDQwNGFjNTA0MWZmNWIwNDJjMjlmYjM5N2JlZjQ0ZCIsImNsaWVudHR5cGUiOiJXRUJDTElFTlQiLCJzY29wZSI6WyJvcGVuaWQiLCJGaWluVHJhZGUuTWFya2V0IiwiRmlpblRyYWRlLkNvcmUiLCJGaWluVHJhZGUuUmVhbHRpbWUiLCJGaWluVHJhZGUuRnVuZGFtZW50YWwiXSwiYW1yIjpbInB3ZCJdfQ.RSMsirz2etpYNVx9Pq1W1qExw1ETwCt5XUxglHwreyQX0WDZV3nUDOf5mxgNKjQx_sPCBQuF6SBH8IdNGcuv9ajvd2XbKWdcsNljXidiRHNGogo-JKIZIqadzLAEAmdXoYP_w2ToqOYkWmtEzm2SMpgbVzklRftciQg4h-K_jYW4YpteX23Az78yT3_RIirfBfszaTp5v3BEOR_StHG16bHPauOlIGmch6o6cWUSX1RPnqyAUVaNGELPygNQcmoYVgyQhwoloXyuDY7LGjhK3EgMm9iCuDx5JasFi5A0PQrAfgs1g7UftC-B_7XvJG4pw4qbevj3PehvZ9Kp1RshXw&token_type=Bearer&expires_in=28600&scope=openid%20FiinTrade.Market%20FiinTrade.Core%20FiinTrade.Realtime%20FiinTrade.Fundamental&state=19e5bb5a7df14a2bab8ded1f265a7bda&session_state=dV3zKwxom21hMpGaoJweGLKUlj2rO2gGSFWbw6bIw4U.ab1d0e2f49d55710dba656b0c958891d
I finally figured it out using Selenium. Here is the code:
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium import webdriver
LOGIN_URL = 'https://auth.fiintrade.vn/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DStoxPlus.FiinTrade.SPA%26redirect_uri%3Dhttps%253A%252F%252Ffiintrade.vn%252Fsignin-callback%26response_type%3Did_token%2520token%26scope%3Dopenid%2520FiinTrade.Market%2520FiinTrade.Core%2520FiinTrade.Realtime%2520FiinTrade.Fundamental%26state%3Dd454e517f7ff44709a797670cd357be7%26nonce%3D890d02d7b58f42e88197818b035ad6d9%26clientType%3DWEBCLIENT%26fp%3De292f9093f0b9abc9904b5fba1d948c6%26type%3Dredirect'
def generate_token() -> bool:
service = Service(cfg.CHROME_DRIVER_PATH)
options = Options()
options.headless = True # do not show new window
driver = webdriver.Chrome(service=service, options=options)
driver.get(LOGIN_URL)
username_textbox = driver.find_element(By.ID, "exampleInputEmail1")
username_textbox.send_keys(cfg.USERNAME)
password_textbox = driver.find_element(By.ID, "exampleInputPassword1")
password_textbox.send_keys(cfg.PASSWORD)
login_button = driver.find_element(By.NAME, "button")
login_button.click()
assert 'access_token=' in driver.current_url, 'Failed to get access token'
resp = driver.current_url
# get token from resp
resp = resp.split('access_token=')[1].split('&token_type=')
id_token = resp[0]
token_type = resp[1].split('&expires_in=')[0]
auth_token = token_type + ' ' + id_token
with open(cfg.AUTH_TOKEN_SAVE_PATH, 'w') as f:
f.write(auth_token)
return 0

Python Fastapi. No headers after redirect

I'm doing a test via "test_client" and testing the "/me" endpoint which redirects, depending on the incoming token, to the secure endpoint either /users/user_id or /operators/operator_id. But after redirection headers become None`.
If I doing it via swagger - all works correctly, if I doing this via curl - I'm don't getting an answer at all.
So, the main problem is that headers are becoming are empty (no token) after redirection.
There is my code:
#app.api_route(path="/me",
status_code=308,
methods=["GET", "DELETE", "PATCH"],
tags=['me'],)
def get_my_profile(request: fastapi.Request, token: str = fastapi.Depends(config.oauth2_scheme), ):
token_payload = services_get_token_payload(token=token)
if token_payload['role'] == config.USER_ROLE:
url = f"{request.url.scheme}://{config.APP_IP}:{config.APP_PORT}/users/{token_payload['sub']}"
elif token_payload['role'] == config.OPERATOR_ROLE:
url = f"{request.url.scheme}://{config.APP_IP}:{config.APP_PORT}/operators/{token_payload['sub']}"
elif token_payload['role'] == config.EMPLOYEE_ROLE:
url = f"{request.url.scheme}://{config.APP_IP}:{config.APP_PORT}/employees/{token_payload['sub']}"
else:
raise fastapi.HTTPException('Can not redirect, some error occurred')
return fastapi.responses.RedirectResponse(url=url, status_code=308, headers=request.headers) # No matter `request.headers` or `dict(request.headers)`
#router.get(path="/{user_id}", status_code=200, response_model=schemas.UserOut)
async def get_user(
user_id: int = Path(default=...),
token: str = Depends(config.oauth2_scheme), # error during checking, no headers
postgres_session: AsyncSession = Depends(database.get_db),):
token_payload = services.get_token_payload(token=token)
services.verify_access(role=token_payload["role"], true_conds=token_payload['sub'] == user_id)
user = await crud.read_user(statement=users.select().where(users.c.id == user_id), db_session=postgres_session)
return schemas.UserOut(**user)
Proof with curl:
david#david-ThinkPad-E480:~$ curl -X 'GET' \
> 'http://127.0.0.1:8000/me' \
> -H 'accept: */*' \
> -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2IiwiZXhwIjoxNjIyNjc3NzgwLCJyb2xlIjoxLCJjaGF0X3Rva2VuIjp7ImlkZW50aXR5Ijo2LCJ0b2tlbiI6ImV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSklVekkxTmlJc0ltTjBlU0k2SW5SM2FXeHBieTFtY0dFN2RqMHhJbjAuZXlKcWRHa2lPaUpUU3pWaFpEVXpZV1UzTWpnek1XWTJORGRoWm1RNU1qQmlabUl6TW1Gak1XRTBMVEUyTWpFMU9UYzNPREFpTENKbmNtRnVkSE1pT25zaWRtbGtaVzhpT250OUxDSmphR0YwSWpwN0luTmxjblpwWTJWZmMybGtJam9pU1ZNelkyVTFNR1l3TnpnNE9HWTBaV1ZrT1dJM05ESXpZMlExWTJaa01EbG1OQ0o5TENKcFpHVnVkR2wwZVNJNk5uMHNJbWx6Y3lJNklsTkxOV0ZrTlROaFpUY3lPRE14WmpZME4yRm1aRGt5TUdKbVlqTXlZV014WVRRaUxDSmxlSEFpT2pFMk1qRTJNREV6T0RBc0ltNWlaaUk2TVRZeU1UVTVOemM0TUN3aWMzVmlJam9pUVVObU9ESTNORFJrTkRCbVlUTmxNbUZpTlRkbU56WTBOREV4TmpCaU5UUmlaQ0o5LnBzeVpJbE9OeTRRX2pNeHNnREswUUI2X3l4T20xcUZ6eVEyajczSHVvaWMifX0.c66ACoJpTLRXYMeysEYwUIQJSqIMEXegXRn4vc0sIMw'
david#david-ThinkPad-E480:~$

Send email with MailerSend API and R

I am trying to use the transaction email service MailerSend to send an email from R.
They have cURL instructions as to how to do this.
I don't think I have the formatting quite right as I get the error:
> response
Response [https://api.mailersend.com/v1/email]
Date: 2021-02-26 19:49
Status: 401
Content-Type: application/json
Size: 30 B
> rsp_content <- content(response, as = "parsed", type = "application/json")
> rsp_content
$message
[1] "Unauthenticated."
R Script to send an email
library("httr")
# MailerSend API Key
apiKeyMS <- Sys.getenv("MS_KEY")
# Email header info
email_from = "noreply#example.ca"
email_from_name = "Joe"
email_subject <- "Joe Update"
email_to <- "joe#gmail.com"
# Email Body
email_text <- "This is my email"
email_html <- "This is my email"
# Send Email
ms_url <- paste0("https://api.mailersend.com/v1/email")
response <- POST(ms_url,
add_headers("Authorization: Bearer" = apiKeyMS,
"X-Requested-With" = "XMLHttpRequest",
"Content-Type" = "application/json"),
body = list(
"subject" = email_subject,
"from" = email_from,
"from_name" = email_from_name,
"to" = email_to,
"text" = email_text,
"html" = email_html
), encode = "json")
#############################################################
Basic MailerSend cURL instructions
curl -X POST \
https://api.mailersend.com/v1/email \
-H 'Content-Type: application/json' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Authorization: Bearer {place your token here without brackets}' \
-d '{
"from": {
"email": "your#email.com"
},
"to": [
{
"email": "your#email.com"
}
],
"subject": "Hello from MailerSend!",
"text": "Greetings from the team, you got this message through MailerSend.",
"html": "Greetings from the team, you got this message through MailerSend."
}'
I don't know R at all, but I would guess your bearer token is incorrect.
The header key is Authorization and the value should be "Bearer {place your token here without brackets}"
You have to have these three headers
-H 'Content-Type: application/json' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Authorization: Bearer {place your token here without brackets}' \`

Pass POST data to unix domain socket through nginx

I have a unix domain socket file and it is working with with nc command. Now I want to access it via nginx but it does not work. Am I missing something?
test with nc => it works
$ echo '{ "method" : "getinfo", "params" : [], "id" : "1" }' | nc -U /home/zono/.lightning/lightning-rpc
{ "jsonrpc": "2.0", "id" : "1", "result" :
{
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
test via nginx => it does not work
// /etc/nginx/sites-enabled/default
upstream nginx-internal-sock {
server unix:/home/zono/.lightning/lightning-rpc;
}
server {
listen 80;
location / {
proxy_pass http://nginx-internal-sock;
}
}
$ curl -H "content-type: application/json" -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
2019-03-20T04:25:52.551Z lightningd(30143):jcon fd 32: Invalid token in json input: 'POST / HTTP/1.0??Host: nginx-internal-sock??Connection: close??C'
Update 1
There's been a development. However I can't get whole data.
// install nginx-extras
apt-get install nginx-extras
// /etc/nginx/sites-enabled/default
server {
listen 80;
location / {
content_by_lua '
ngx.req.read_body()
local body_data = ngx.req.get_body_data()
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/home/zono/.lightning/lightning-rpc")
local bytes = sock:send(body_data)
local line, err = sock:receive("*a")
ngx.say(line)
ok, err = sock:close()
';
}
}
// Response is nil
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
nil
// /var/log/nginx/error.log
2019/03/20 07:43:39 [error] 4926#4926: *35 lua tcp socket read timed out, client: 127.0.0.1, server: , request: "POST / HTTP/1.1", host: "127.0.0.1"
// When I set "sock:receive("*l")" the response is the part of the data.
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
{ "jsonrpc": "2.0", "id" : "1", "result" :
I'm checking the reference now. http://w3.impa.br/~diego/software/luasocket/tcp.html
'*a': reads from the socket until the connection is closed. No end-of-line translation is performed;
'*l': reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;
number: causes the method to read a specified number of bytes from the socket.
I found out the answer.
// install nginx-extras
apt-get install nginx-extras
// /etc/nginx/sites-enabled/default
server {
listen 80;
location / {
content_by_lua '
ngx.req.read_body()
local body_data = ngx.req.get_body_data()
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/home/zono/.lightning/lightning-rpc")
local bytes = sock:send(body_data)
local readline = sock:receiveuntil("\\n\\n")
local line, err, part = readline()
if line then
ngx.say(line)
end
ok, err = sock:close()
';
}
}
// curl
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1

Resources