Hello community …
I encountered a blocking error while sending outgoing messages from CHT 4.18 to Textit .. On investigating the api logs i noticed this error
2025-04-25T16:39:01.583 DEBUG: Checking for a configured outgoing message service
2025-04-25T16:39:01.583 DEBUG: Checking for pending outgoing messages
2025-04-25T16:39:01.594 INFO: Sending 1 messages
2025-04-25T16:39:02.866 ERROR: Error thrown when trying to send message: Error: 403 - "<html lang=\"en\">\n <head>\n <title>Page - Not Found</title>\n <style>\n body {\n background: var(--color-primary-dark);\n font-family: \"Helvetica Neue\", Arial, \"Lucida Grande\", sans-serif;\n color: #555;\n }\n\n .home {\n margin: 10em auto;\n margin-bottom: 1em;\n max-width: 400px;\n text-align: center;\n }\n\n .logo img {\n max-width: 100%;\n }\n\n .message {\n margin: 0 auto;\n margin-top: 10px;\n color: #333;\n text-align: center;\n max-width: 450px;\n }\n </style>\n </head>\n <body>\n <div class=\"home\">\n <h3><a href=\"/\">Home</a></h3>\n </div>\n <div style=\"text-align: center;\">\n <h3>Something doesn't seem right.</h3>\n </div>\n <div class=\"message\">\n We couldn't find the page you are looking for.\n <br />\n If you think we've made a mistake,\n <br />\n contact support and we will look into it.\n </div>\n </body>\n</html>\n"
at request (/service/shared-libs/couch-request/src/couch-request.js:183:15)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
[stack]: [Getter/Setter],
[message]: `403 - "<html lang=\\"en\\">\\n <head>\\n <title>Page - Not Found</title>\\n <style>\\n body {\\n background: var(--color-primary-dark);\\n font-family: \\"Helvetica Neue\\", Arial, \\"Lucida Grande\\", sans-serif;\\n color: #555;\\n }\\n\\n .home {\\n margin: 10em auto;\\n margin-bottom: 1em;\\n max-width: 400px;\\n text-align: center;\\n }\\n\\n .logo img {\\n max-width: 100%;\\n }\\n\\n .message {\\n margin: 0 auto;\\n margin-top: 10px;\\n color: #333;\\n text-align: center;\\n max-width: 450px;\\n }\\n </style>\\n </head>\\n <body>\\n <div class=\\"home\\">\\n <h3><a href=\\"/\\">Home</a></h3>\\n </div>\\n <div style=\\"text-align: center;\\">\\n <h3>Something doesn't seem right.</h3>\\n </div>\\n <div class=\\"message\\">\\n We couldn't find the page you are looking for.\\n <br />\\n If you think we've made a mistake,\\n <br />\\n contact support and we will look into it.\\n </div>\\n </body>\\n</html>\\n"`,
body: '<html lang="en">\n' +
' <head>\n' +
' <title>Page - Not Found</title>\n' +
' <style>\n' +
' body {\n' +
' background: var(--color-primary-dark);\n' +
' font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif;\n' +
' color: #555;\n' +
' }\n' +
'\n' +
' .home {\n' +
' margin: 10em auto;\n' +
' margin-bottom: 1em;\n' +
' max-width: 400px;\n' +
' text-align: center;\n' +
' }\n' +
'\n' +
' .logo img {\n' +
' max-width: 100%;\n' +
' }\n' +
'\n' +
' .message {\n' +
' margin: 0 auto;\n' +
' margin-top: 10px;\n' +
' color: #333;\n' +
' text-align: center;\n' +
' max-width: 450px;\n' +
' }\n' +
' </style>\n' +
' </head>\n' +
' <body>\n' +
' <div class="home">\n' +
' <h3><a href="/">Home</a></h3>\n' +
' </div>\n' +
' <div style="text-align: center;">\n' +
" <h3>Something doesn't seem right.</h3>\n" +
' </div>\n' +
' <div class="message">\n' +
" We couldn't find the page you are looking for.\n" +
' <br />\n' +
" If you think we've made a mistake,\n" +
' <br />\n' +
' contact support and we will look into it.\n' +
' </div>\n' +
' </body>\n' +
'</html>\n',
status: 403,
ok: false,
headers: Headers {
date: 'Fri, 25 Apr 2025 16:39:02 GMT',
'content-type': 'text/html',
'content-length': '992',
connection: 'keep-alive',
server: 'nginx',
etag: '"6627a17e-3e0"',
'strict-transport-security': 'max-age=31536000; includeSubDomains',
'x-content-type-options': 'nosniff',
'x-frame-options': 'DENY'
},
[Symbol(state)]: Proxy [
{
aborted: false,
rangeRequested: false,
timingAllowPassed: true,
requestIncludesCredentials: true,
type: 'default',
status: 403,
timingInfo: {
startTime: 167347074.999293,
redirectStartTime: 0,
redirectEndTime: 0,
postRedirectStartTime: 167347074.999293,
finalServiceWorkerStartTime: 0,
finalNetworkResponseStartTime: 167348337.558451,
finalNetworkRequestStartTime: 167348043.845515,
endTime: 0,
encodedBodySize: 992,
decodedBodySize: 992,
finalConnectionTimingInfo: {
domainLookupStartTime: 167347074.999293,
domainLookupEndTime: 167347074.999293,
connectionStartTime: 167347074.999293,
connectionEndTime: 167347074.999293,
secureConnectionStartTime: 167347074.999293,
ALPNNegotiatedProtocol: undefined
}
},
cacheState: '',
statusText: 'Forbidden',
headersList: HeadersList {
cookies: null,
[Symbol(headers map)]: Map(9) {
'date' => [Object],
'content-type' => [Object],
'content-length' => [Object],
'connection' => [Object],
'server' => [Object],
'etag' => [Object],
'strict-transport-security' => [Object],
'x-content-type-options' => [Object],
'x-frame-options' => [Object]
},
[Symbol(headers map sorted)]: null,
[entries]: [Getter],
[entriesList]: [Getter]
},
urlList: [
URL {
href: 'https://textit.com/api/v2/broadcasts.json',
origin: 'https://textit.com',
protocol: 'https:',
username: '',
password: '',
host: 'textit.com',
hostname: 'textit.com',
port: '',
pathname: '/api/v2/broadcasts.json',
search: '',
searchParams: URLSearchParams {},
hash: '',
[Symbol(context)]: URLContext {
href: 'https://textit.com/api/v2/broadcasts.json',
protocol_end: 6,
username_end: 8,
host_start: 8,
host_end: 18,
pathname_start: 18,
search_start: 4294967295,
hash_start: 4294967295,
port: 4294967295,
scheme_type: 2,
[hasPort]: [Getter],
[hasSearch]: [Getter],
[hasHash]: [Getter]
}
},
[length]: 1
],
body: {
stream: ReadableStream { locked: true, state: 'closed', supportsBYOB: true },
source: null,
length: null
}
},
{
get: [Function: get] { [length]: 2, [name]: 'get' },
set: [Function: set] { [length]: 3, [name]: 'set' }
}
],
[Symbol(headers)]: Headers {
date: 'Fri, 25 Apr 2025 16:39:02 GMT',
'content-type': 'text/html',
'content-length': '992',
connection: 'keep-alive',
server: 'nginx',
etag: '"6627a17e-3e0"',
'strict-transport-security': 'max-age=31536000; includeSubDomains',
'x-content-type-options': 'nosniff',
'x-frame-options': 'DENY'
}
}
which i believe is happen while sending messages to the Textit /api/v2/broadcasts.json
api endpoint. We can refactor the code to add a custom User-Agent header ie
headers: {
Authorization: `Token ${apiToken}`,
'User-Agent': 'CHT-Core-RapidPro-Integration/1.0'
},
as we had done for the outbound feature a while back because Textit want this to be added for all api requests made
cc @diana @twier @antony