I can't send headers with feathersJS rest api /axios. What do I do wrong? - axios

I have feathers API with REST/axios. Configured like this:
const axios = require("axios");
const restClient = rest(serverPaths.serverPath.slice(0, -1));
restApi.configure(restClient.axios(axios.create({
headers: {accessToken: '--change---me'} // this works all the time
})));
The request:
const sr = await this.$restApi.service('users').find({}, {
headers: {
accesstoken: '-this is a new token-' // this does not work
}
});
However simply changing to get and it works:
const sr = await this.$restApi.service('users').get(1, {
headers: {
accesstoken: '-this is a new token-' // now it works
}
});
So for get I receive: accesstoken: --change---me, -this is a new token- so both of them, which is fine, I'll just delete the first one from config file.
But that's mean I do something wrong. Something simple and stupid but I just can't figure it out what.
Note: all regular API request with axios, not using feathers services, works without problem, I can send any header I want and it just work.

Related

Create http request from cloud functions with header and response

I'm currently developing a flutter app that sends some http requests to an external service, but actually, I keep some API keys in the app, and I want to secure them using cloud functions. How can I create a function that executes something like this? This is a Stripe request that I actually make from the app.
Future<Customer?> createCustomer(String userId) async {
final String url = 'https://api.stripe.com/v1/customers';
Map<String,String> headers = {
'Authorization': 'Bearer <API_KEY_HERE>',
'Content-Type': 'application/x-www-form-urlencoded'
};
var response = await _client.post(
Uri.parse(url),
headers: headers,
body: {'name': "test", "metadata[userId]": userId},
);
final decodedResult = json.decode(response.body);
log.info(decodedResult);
if (response.statusCode == 200) {
try {
final customer = Customer.fromMap(decodedResult);
currentCustomer = customer;
return customer;
} catch (e) {
log.error(e.toString());
return null;
}
} else {
return null;
}
}
You cloud very well, from a Cloud Function, call the Stripe REST API with, for example, the axios library.
But since we use the Admin SDK for Node.js to write Cloud Functions for Firebase, I would suggest to use the Stripe Node.js API (This link points to the customers.create method).
You can do that from any type of Cloud Function, e.g. a Callable one that you call from your app or a background triggered one, e.g. when a new customer doc is created in a Firestore collection.
The following search on SO will return many code examples: https://stackoverflow.com/search?q=Firebase+Cloud+Functions+stripe

How do I await a .wasm (WebAssembly file) from a Rest API?

I am making a Next.js app that has a page that connects to a REST API. The REST API simply spits out a raw .wasm (WebAssembly) file. I know that sounds atypical but it's 100% necessary for my app. I have this function which is supposed to fetch the .wasm file from the API:
const fetchedWasmWrapped = useCallback( async () => {
const endpoint = "/.netlify/functions" + "/decrypt?authSig="+JSON.stringify(props.props.authSig);
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/wasm',
},
};
const response = await fetch(endpoint, options);
const result = await response.text();
console.log(result);
setDecryptedWasm(result);
}, [props.props.authSig])
The function works. It DOES output the .wasm file but console.log(result) writes a bizarre string with a lot of symbols and empty characters. I believe the reason why result is all jumbled up is because I don't think WebAssembly is meant to be printed as a string. It's actually a blob. result is then read as a file later in my app but that fails and I'm assuming it's because the WebAssembly code was not imported as a blob but rather a string.
So how do I tell typescript that I want the ".wasm" code from response? I don't believe there a response.wasm() function so how do I do this?
The key is that you have to change const result = await response.text(); to const result = await response.blob();
This threw more errors in my vscode terminal because setDecryptedWasm was expecting a string. So change const [decryptedWasm, setDecryptedWasm] = useState(''); to const [decryptedWasm, setDecryptedWasm] = useState(new File([], ''));
And rather than setting decryptedWasm with setDecryptedWasm(result), do setDecryptedWasm(new File([result], 'myunityapp.wasm'));

Url as req.params in Express

I'd like to use express and mongo DB to find a document based off of a URL.
My Schema includes
bandUrl: {
type: String
}
This is my Rout inside of the Express server.
// Get Single Band By bandUrl
router.get('/bandUrl/:url', (req, res) => {
quoteGenerator.find({bandUrl: req.params.url}).then(gen => res.json(gen))
})
I set one of the documents to have bandUrl as 'http://localhost:3000/'.
I tested the route using something other than a URL - just using a string works fine... I'd really like to use the URL though. Is there a way to do this?
Here is my fake/test route form the application..
const getFakeInfo = async () => {
try {
const response = await fetch(`/api/autoquotegenerators/bandUrl/http://localhost:3000/"`, {
method: 'GET',
})
const responseData = await response.json()
console.log(responseData)
} catch (error) {
console.log(error)
}
}
I am thinking the extra slashes in the URL are whats causing the issue.
Thanks for your help!
What you want to you use is encodeURIComponent(). This function escapes all URI specific characters, so they get interpreted properly. Your request code should look something like this:
const response = await fetch(`/api/autoquotegenerators/bandUrl/${encodeURIComponent("http://localhost:3000/")}`, {
method: 'GET',
})
If you want to learn more about this function, you can have a look over here.

Dart HttpClient not reading full response

I have a weird issue using the dart HttpClient where it seems like it's not reading the full response before "finishing". This is the code I have:
HttpClient client = new HttpClient();
client.connectionTimeout = Duration(seconds: 60);
Completer<MealPlan> completer = new Completer();
RecipeSearchFilter filter = new RecipeSearchFilter();
filter.restrictions = intolerances.map((intolerance) => intolerance.name).toList();
MealPlan mealPlan;
client
.getUrl(Uri.parse(
"https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}"))
.then((HttpClientRequest request) {
request.headers.set("Authorization", "Bearer $idToken");
return request.close();
}).then((HttpClientResponse response) {
response.transform(utf8.decoder).listen((contents) {
Map<String, dynamic> contentMap = jsonDecode(contents);
mealPlan = MealPlan.fromJson(contentMap);
}, onDone: () => completer.complete(mealPlan));
});
return completer.future;
This is the most intensive function that my app contains, so this particular API itself typically takes 6-8 seconds to fully complete since there's a lot going on behind the scenes. The response isn't big (~60KB). Making the exact same call using Postman I can see that it does indeed return everything as expected, but if I look at the response inside of the }).then((HttpClientResponse response) { block, it only contains a very small, partial bit of the response. I'm not sure what I'm doing wrong here, but I'm guessing that I've configured the HttpClient incorrectly.
The problem is that your response will be delivered by the stream in pieces. After passing those chunks through the utf8 decoder, you should then form them into a single string before trying to json decode it. Currently you try to json decode the first chunk without waiting for the rest.
It's much easier to use the package:http which is a wrapper around HttpClient, and does a lot of the grunt work for you. Also, it's more readable to use the async/await syntax rather than .then.
Using an async method you could write, for example:
void getPlan(Map filter, String idToken) async {
var response = await http.get(
Uri.parse('https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}'),
headers: <String, String>{
'Authorization': 'Bearer $idToken',
},
);
return MealPlan.fromJson(json.decode(response.body));
}
If you really want to control the connection timeout, you need to pass in your own HttpClient, as follows:
var client =
http.IOClient(HttpClient()..connectionTimeout = Duration(seconds: 60));
var response = await client.get(
//etc

How can I access DialogFlow parameters using DialogFlowApp or ActionsSDKApp client library?

I'm using DialogFlow to create a Google Assistant Application. For fullfilment I'm using a custom app with NodeJS client library.
I noted that when DialogFlow's request get my application I can see all request, also the parameters object
const astronomyAssistant = functions.https.onRequest((request, response) => {
const app = new DialogflowApp({ request, response });
console.log(`Request headers: ${JSON.stringify(request.headers)}`);
console.log(`Request body: ${JSON.stringify(request.body)}`);
app.handleRequest(actionMap);
});
There some way to access the request object inside of a handle action? How can I access request object using app?
Workaround:
You can put all handle function that depends of request object inside of functions.https.onRequest callback.
For instance:
const astronomyAssistant = functions.https.onRequest((request, response) => {
const app = new DialogflowApp({ request, response });
console.log(`Request headers: ${JSON.stringify(request.headers)}`);
console.log(`Request body: ${JSON.stringify(request.body)}`);
const foo = app => {
console.log(request);
}
actionMap.set('input.foo', foo);
app.handleRequest(actionMap);
});
But, for sure this is not a good practice.
You can use app.getArgument("my-parameter") to quickly access any parameter you've defined within your actions.