For 2 days now, I have the issue that my lambda function using the ask-sdk-core v2.0.2 returns invalid responses.
A very simple setup:
HelloIntent is handled by HelloIntentHandler:
const HelloIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'HelloIntent';
},
handle(handlerInput) {
const speechText = 'Hello back';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
When I call this intent, the simulator goes straight to:
There was a problem with the requested skill's response
Using the ErrorHandler, I checked and the results of handlerInput.requestEnvelope.request.error are:
{ type: 'INVALID_RESPONSE',
message: 'An exception occurred while dispatching the request to the skill.' }
Question: What is the problem here? When I open the skill using the invocation name, the LaunchRequestHandler gets called and responds properly, but any other intent does not work.
Okay I found the problem, it is sort of difficult to deduct from the above error:
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloIntent';
},
In the canHandle function, you need to check for the request type and intent name.
Related
I'm creating an application that is using Nestjs with websockets, but now I need to add rate limit on the sockets, but analyzing the documentation documentation link and implementing what it says in it, when I use #UseGuards(MyGuard) an error occurs in the application.
My Guard:
#Injectable()
export class NewThrottlerGuard extends ThrottlerGuard {
protected async handleRequest(
context: ExecutionContext,
limit: number,
ttl: number,
): Promise<boolean> {
console.log('Request');
const client = context.switchToWs().getClient();
const ip = client.conn.remoteAddress;
const key = this.generateKey(context, ip);
const ttls = await this.storageService.getRecord(key);
if (ttls.length >= limit) {
throw new ThrottlerException();
}
await this.storageService.addRecord(key, ttl);
return true;
}
}
Websocket:
#UseGuards(NewThrottlerGuard)
#SubscribeMessage('sendMessage')
sendMessage(
#ConnectedSocket() client: Socket,
#MessageBody() message: string,
) {
client.rooms.forEach((room) => {
if (room !== client.id) {
client.broadcast.to(room).emit('message', message);
}
});
}
Error in console:
/node_modules/#nestjs/common/utils/validate-each.util.js:22
throw new InvalidDecoratorItemException(decorator, item, context.name);
^
Error: Invalid guard passed to #UseGuards() decorator (ChatGateway).
at validateEach
The file in: #nestjs/common/utils/validate-each.util.js:22
function validateEach(context, arr, predicate, decorator, item) {
if (!context || !context.name) {
return true;
}
console.log(context, arr)
const errors = arr.some(str => !predicate(str));
if (errors) {
throw new InvalidDecoratorItemException(decorator, item, context.name);
}
return true;
}
i put some console.log then in the terminal it show:
[Function: ChatGateway] [ undefined ]
In Github Throttler documentation they say: You cannot bind the guard with APP_GUARD or app.useGlobalGuards() due to how Nest binds global guards.
So, im using #UseGuards()
The guard itself was written correctly, but it was put in a location that importing it made a circular reference between files, so when #UseGuards() was used it became #UseGuards(undefined) which caused the cryptic error message. Moving the guard to a dedicated file will fix the error
I follow your github reference settings and it doesn't work,The following is my code, where is my setting wrong, and the request to ws is not intercepted(In the handleRequest method)
I'm having trouble getting a response from a callback uri and I would really appreciate any help you could give me.
I am trying to use the Fitbit API which requires you to use a callback url to get an Auth Code.
Workflow:
1. Go to Fitbit url to get user to allow the app access to their personal data.
2. User agrees to the conditions
3. User gets redirected to my API
4. The API returns the code from (Code is located in URL and I can access it)
5. I console.log the code out to verify it
6. API returns the code
7. I work with code then exchanging it for an access token.
The problem is that I don't return the code (Or anything )when I return to the app even though I can console.log it on the API. The response I get is NULL
Here is the URL:
url = "https://www.fitbit.com/oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https://REDIRECT_URL&scope=activity%20heartrate%20location%20nutrition%20profile%20settings%20sleep%20social%20weight&expires_in=604800";
I then open the URL in the InAPPBrowser successfully:
if (url !== "") {
const canOpen = await Linking.canOpenURL(url)
if (canOpen) {
try {
const isAvailable = await InAppBrowser.isAvailable()
if (isAvailable) {
const result =InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'done',
preferredBarTintColor: 'gray',
preferredControlTintColor: 'white',
// Android Properties
showTitle: true,
toolbarColor: '#6200EE',
secondaryToolbarColor: 'black',
enableDefaultShare: true,
}).then((result) => {
console.log("Response:",JSON.stringify(result))
Linking.getInitialURL().then(url => {
console.log("Tests: ",url)
this._setTracker(url as string);
});
})
} else Linking.openURL(url)
} catch (error) {
console.log("Error: ",error)
}
}
}
From here the URL opens successfully.
Here is the API now which is done in Typescript on AWS serverless and Lambda
export const handler: APIGatewayProxyHandler = async (event, _context, callback) =>{
let provider = event.path
//prints code
let x = event.queryStringParameters
console.log("Code: ",x)
const response = {
statusCode: 200,
body: "Success"
};
return response;
}
Please let me know if further detail is required?
Thank you!
Right so it turns out what I was doing was correct apart from the response should have been 301 which is a redirect response.
const response= {
statusCode: 301,
headers: {
"location": `app://CALLBACK RESPONSE ADDRESS?type=${provider}`
},
body: "Boom"
}
How to make through an interval requests before tests?
I tried 2 ways to retry requests but either was failing;
I need to upload a file, waiting till one got imported successfully
On the first step i upload a file to my server in cypress
before( ()=> {
//my custom POST command
cy.form_request(url, data)
.then(({id}) => {
Then i wait for id of the uploaded file
check_It_Till_Success_It(id);
})
})
Then the received id i pass into a new request to verified its status on the server and need to repeat the request till the file processing is finished.
At the solution below it says
CypressError: cy.wait() only accepts aliases for routes.
The alias: 'check_it_request' did not match a route.
function check_It_Till_Success_It(id) {
function checkRequest() {
cy.request("GET", "http://localhost:28080/admin/api/catalog/import/status/" + id)
.then(({status}) => {
if (status === "FINISHED" || status === "FAILED") {
clearInterval(check_It);
} else {
console.log('retry one more time');
}
}).as('check_it_request');
cy.wait("#check_it_request");
}
checkRequest();
const check_It = setInterval(checkRequest, 1000);
}
or here is another my solution through a recursive requesting:
function check_It_Till_Success_It(id) {
return (
cy.request("GET", BASE_URL + "/admin/api/catalog/import/status/" + id)
.then(({status}) => {
if (status === "FINISHED" || status === "FAILED") {
console.log('success');
} else {
console.log('retry one more time');
setTimeout(() => check_It_Till_Success_It(id), 1000)
}
})
)
}
but it throws an error:
Uncaught CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
What am i doing wrong?
I found my mystake because of the use of native JS tools as setTimeout, setInterval.
Cypress doesnt allow to use them and replaces with controllable methods: cy.clock and cy.tick
So i took the recursion implementation and replaced with the methods above and my code became:
function check_It_Till_Success_It(id) {
cy.request("GET", BASE_URL + "/admin/api/catalog/import/status/" + id)
.then(resp => {
const status = resp.body.status;
if (status === "FINISHED" || status === "FAILED") {
console.log('success');
} else {
console.log('retry one more time');
cy.clock();
cy.tick(1000);
check_It_Till_Success_It(id)
}
})
}
Offtopic note: I'm new with Cypress and as i understood it replaces the most of the js native features so it's needed to look the docs much closer (BINGO!) or look at issue section because some JS specific feature just crash Cypress without any notification or catched error, for example: FormData object crashed Cypress'es request method.
I'm having trouble promises and observables. I have a handful of http requests which are defined in a package using promises. In the rest of my code I am using observables for various things, including other http calls. In one particular section I am checking to see if the user's bearer token is expired and if so then I get a new token and then proceed with the rest of the call.
if (!token || token.exp < Math.round((new Date()).getTime() / 1000)) {
from(this._store.refreshBearerToken())
.pipe(flatMap(resp => {
let newToken = resp.data;
newToken.exp = (new Date()).getTime() / 1000 + newToken.expires_in;
localStorage.setItem('token', JSON.stringify(newToken))
options = options || {};
options.headers = new HttpHeaders({
"Authorization": `${newToken.token_type} ${newToken.access_token}`,
"Content-Type": "application/json"
});
return this._http$.request<T>(method, url, options as Object).pipe(share());
}));
}
Bearer Token method:
async refreshBearerToken() {
const response = await this._q2.sources.requestExtensionData({
route: "refreshBearerToken"
});
console.log(response);
return response;
}
Since this._store.refreshBearerToken returns a promise I wrapped the call in a from to convert it to an observable. This compiles but when it runs I get "Cannot read property 'pipe' of undefined".
How can I convert this promise to an observable so that I can refresh the token and then continue with the rest of the call?
Edit:
I am importing from via import { Observable, from } from "rxjs";.
So, I thought the error was coming from the line .pipe(flatMap(resp =>... but I was wrong. The error is coming from the method which is calling this.
GetInitialLinkList(): Observable<Institution[]>
{
let base = { 'MemberId': localStorage.getItem('memberId') };
let ins = localStorage.getItem("initialInstitutionList");
if (ins)
{
return of(JSON.parse(ins));
}
return this._settingsService.get().pipe(
flatMap(settings =>
{
this._settings = settings;
return this._api.request<Institution[]>("Post", `${this._settings.mea}/GetInitialLinkList`, { body: base })
.pipe(
retry(1),
catchError(this.handleError)
)
.pipe(flatMap(instList =>
{
localStorage.setItem("initialInstitutionList", JSON.stringify(instList));
return of(instList);
}))
}));
}
and that is being subscribed to inside my component:
private GetLinkList()
{
this.showWaiting.emit(true);
this._data.GetInitialLinkList().subscribe((result) =>
{
this.initialList = result;
this.showWaiting.emit(false);
});
}
From what Brandon said (I forgot to return /facepalm...) I added the return so I have return from(this._store.refreshBearerToken()) which changed my error to
ERROR Error Code: undefined
Message: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
defaultErrorLogger # core.js:6014
Can you show the actual error and the line in the code that the error occurs on? Also show where and how you import from.
I notice your code snippet does not return the observable it builds up via from(...).pipe(...) nor does it subscribe to it. It might help to show how your code actually uses this observable.
I'm trying to write a test for the Jasmine Test Framework which expects an error. At the moment I'm using a Jasmine Node.js integration from GitHub.
In my Node.js module I have the following code:
throw new Error("Parsing is not possible");
Now I try to write a test which expects this error:
describe('my suite...', function() {
[..]
it('should not parse foo', function() {
[..]
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
});
});
I tried also Error() and some other variants and just can't figure out how to make it work.
Try using an anonymous function instead:
expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
you should be passing a function into the expect(...) call. Your incorrect code:
// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
is trying to actually call parser.parse(raw) in an attempt to pass the result into expect(...),
You are using:
expect(fn).toThrow(e)
But if you'll have a look on the function comment (expected is string):
294 /**
295 * Matcher that checks that the expected exception was thrown by the actual.
296 *
297 * #param {String} expected
298 */
299 jasmine.Matchers.prototype.toThrow = function(expected) {
I suppose you should probably write it like this (using lambda - anonymous function):
expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");
This is confirmed in the following example:
expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");
Douglas Crockford strongly recommends this approach, instead of using "throw new Error()" (prototyping way):
throw {
name: "Error",
message: "Parsing is not possible"
}
As mentioned previously, a function needs to be passed to toThrow as it is the function you're describing in your test: "I expect this function to throw x"
expect(() => parser.parse(raw))
.toThrow(new Error('Parsing is not possible'));
If using Jasmine-Matchers you can also use one of the following when they suit the situation;
// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
.toThrowAnyError();
or
// I just want to know that an error of
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
.toThrowErrorOfType(TypeError);
A more elegant solution than creating an anonymous function whose sole purpose is to wrap another, is to use ES5's bind function. The bind function creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Instead of:
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
Consider:
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
The bind syntax allows you to test functions with different this values, and in my opinion makes the test more readable. See also:
Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?
I replace Jasmine's toThrow matcher with the following, which lets you match on the exception's name property or its message property. For me this makes tests easier to write and less brittle, as I can do the following:
throw {
name: "NoActionProvided",
message: "Please specify an 'action' property when configuring the action map."
}
and then test with the following:
expect (function () {
.. do something
}).toThrow ("NoActionProvided");
This lets me tweak the exception message later without breaking tests, when the important thing is that it threw the expected type of exception.
This is the replacement for toThrow that allows this:
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
var exception;
if (typeof this.actual != 'function') {
throw new Error('Actual is not a function');
}
try {
this.actual();
} catch (e) {
exception = e;
}
if (exception) {
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
}
var not = this.isNot ? "not " : "";
this.message = function() {
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
} else {
return "Expected function to throw an exception.";
}
};
return result;
};
I know that is more code, but you can also do:
try
Do something
#fail Error("should send a Exception")
catch e
expect(e.name).toBe "BLA_ERROR"
expect(e.message).toBe 'Message'
In my case, the function throwing an error was async, so I followed this:
await expectAsync(asyncFunction()).toBeRejected();
await expectAsync(asyncFunction()).toBeRejectedWithError(...);
For CoffeeScript lovers:
expect( => someMethodCall(arg1, arg2)).toThrow()
For me, the posted solution didn't work and it kept on throwing this error:
Error: Expected function to throw an exception.
I later realised that the function which I was expecting to throw an error was an async function and was expecting the promise to be rejected and then throw an error and that's what I was doing in my code:
throw new Error('REQUEST ID NOT FOUND');
And that’s what I did in my test and it worked:
it('Test should throw error if request not found', willResolve(() => {
const promise = service.getRequestStatus('request-id');
return expectToReject(promise).then((err) => {
expect(err.message).toEqual('REQUEST NOT FOUND');
});
}));
it('it should fail', async () => {
expect.assertions(1);
try {
await testInstance.doSomething();
}
catch (ex) {
expect(ex).toBeInstanceOf(MyCustomError);
}
});