I have set up an OpenAPI connector in Loopback 4 as described here and for unauthorized requests, it is working well; I managed to create the respective datasource, service and controller. My service is similar to the GeocoderProvider example, but, let's say, with the following service interface.
export interface MyExternalService {
search_stuff(params: {query?: string}): Promise<MyExternalServiceResponse>;
}
export interface MyExternalServiceResponse {
text: string;
}
From my controller, I invoke it like this, where this.myExternalService
is the injected service (kind of unrelated, but can Loopback also implicitly parse a JSON response from an external API datasource?):
@get('/search')
async searchStuff(@param.query.string('query') query: string): Promise<void> {
return JSON.parse(
(await this.myExternalService.search_stuff({query})).text,
);
}
Now, the external endpoint corresponding to myExternalService.search_stuff
needs an Authorization: Bearer <token>
header, where the token is sent to Loopback by the client, i.e. it's not a static API key or so. Assuming I added @param.query.string('token') token: string
to the parameter list of my searchStuff
controller method, how can I forward that token to the OpenAPI connector? This is the relevant part of the underlying OpenAPI YAML definition file:
paths:
/search:
get:
security:
- Authorization: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SearchResults'
operationId: search-stuff
components:
securitySchemes:
Authorization:
type: http
scheme: Bearer
I am now using the underlying execute
function of the OpenAPI connector and manually intercept the request (the object that is passed to requestInterceptor
is later passed directly to the http module by Swagger):
return JSON.parse(
(
await this.myExternalService.execute(
'search_stuff',
{query},
{
requestInterceptor: (req: {headers: {Authorization: string}}) => {
req.headers.Authorization = 'Bearer ' + token;
return req;
},
},
)
).text,
);
I also added the following method to the MyExternalService
interface, inspired by the connector's actual execute
function:
execute(
operationId: string,
parameters: object,
options: object,
): Promise<MyExternalServiceResponse>;
Some things I found:
swagger-client
module to do OpenAPI-based requests.securities
option of Swagger's execute function expects a Security Definitions Object. There are some quirks with actually passing it to Swagger as well.securities
key is mentioned, yet is is never actually used for the request. This means that manually specifying it in the third parameter of this.myExternalService.execute
will change nothing.I'll not accept this answer yet and I'm looking forward to finding a more Loopback-like approach.