22
33import logger from '../../utils/Logger.js' // path will likely change
44import Processor from '../../model/Processor.js' // maybe more specific
5+ import fetch from 'node-fetch'
56
67/**
78 * @class HttpClient
@@ -14,10 +15,10 @@ import Processor from '../../model/Processor.js' // maybe more specific
1415 * ### Service Signature
1516 *
1617 * #### __*Settings*__
17- * * **`ns.trm .url`** - The URL to send the HTTP request to
18- * * **`ns.trm .method`** - HTTP method (GET, POST, etc.)
19- * * **`ns.trm .headers`** (optional) - HTTP headers as an object
20- * * **`ns.trm .body`** (optional) - Request body for POST/PUT
18+ * * **`ns.trn .url`** - The URL to send the HTTP request to
19+ * * **`ns.trn .method`** - HTTP method (GET, POST, etc.)
20+ * * **`ns.trn .headers`** (optional) - HTTP headers as an object
21+ * * **`ns.trn .body`** (optional) - Request body for POST/PUT
2122 *
2223 * #### __*Input*__
2324 * * **`message.url`** (if no `configKey`) - The URL to request
@@ -55,14 +56,79 @@ class HttpClient extends Processor {
5556 }
5657
5758 /**
58- * Does something with the message and emits a 'message' event with the processed message.
59+ * Sends an HTTP request and emits a 'message' event with the processed message.
5960 * @param {Object } message - The message object.
6061 */
6162 async process ( message ) {
62- // logger.setLogLevel('debug')
63+ try {
64+ const requestOptions = this . _buildRequestOptions ( message )
65+ logger . debug ( `HttpClient: Sending request to ${ requestOptions . url } with options: ${ JSON . stringify ( requestOptions ) } ` )
6366
64- // processing goes here
65- return this . emit ( 'message' , message )
67+ const response = await this . _sendRequest ( requestOptions )
68+ const processedResponse = await this . _processResponse ( response )
69+
70+ message . http = processedResponse
71+ logger . debug ( `HttpClient: Received response with status ${ response . status } ` )
72+
73+ this . emit ( 'message' , message )
74+ } catch ( err ) {
75+ logger . error ( `HttpClient: Error during HTTP request - ${ err . message } ` )
76+ message . httpError = err . message
77+ this . emit ( 'message' , message )
78+ }
79+ }
80+
81+ /**
82+ * Builds the HTTP request options from config and message.
83+ * @param {Object } message
84+ * @returns {Object } requestOptions
85+ */
86+ _buildRequestOptions ( message ) {
87+ const url = super . getProperty ( 'ns.trn.url' , "https://example.org/" )
88+ const method = super . getProperty ( 'ns.trn.method' , 'GET' ) . toUpperCase ( )
89+ const headers = super . getProperty ( 'ns.trn.headers' , { } )
90+ const body = super . getProperty ( 'ns.trn.body' , null )
91+
92+ const options = { method, headers }
93+ if ( body && ( method === 'POST' || method === 'PUT' || method === 'PATCH' ) ) {
94+ options . body = typeof body === 'string' ? body : JSON . stringify ( body )
95+ if ( ! headers [ 'Content-Type' ] ) {
96+ options . headers [ 'Content-Type' ] = 'application/json'
97+ }
98+ }
99+
100+ return { url, ...options }
101+ }
102+
103+ /**
104+ * Sends the HTTP request using fetch.
105+ * @param {Object } requestOptions
106+ * @returns {Promise<Response> }
107+ */
108+ async _sendRequest ( requestOptions ) {
109+ const { url, ...options } = requestOptions
110+ return fetch ( url , options )
111+ }
112+
113+ /**
114+ * Processes the HTTP response.
115+ * @param {Response } response
116+ * @returns {Promise<Object> } Processed response data
117+ */
118+ async _processResponse ( response ) {
119+ const contentType = response . headers . get ( 'content-type' ) || ''
120+ let data
121+ if ( contentType . includes ( 'application/json' ) ) {
122+ data = await response . json ( )
123+ } else {
124+ data = await response . text ( )
125+ }
126+ return {
127+ status : response . status ,
128+ statusText : response . statusText ,
129+ headers : Object . fromEntries ( response . headers . entries ( ) ) ,
130+ data
131+ }
66132 }
67133}
68134
0 commit comments