switchMap only cancelling some endpoints - http

I have a form control input to search for results.
component.html
<input matInput [formControl]="input">
I'm using valueChanges observable to check for changes.
component.ts
this.xx = this.input.valueChanges.pipe(
switchMap(res => {
return this.someService.test(res);
}),
);
What i don't understand is that on fast typing the cancellation of the previous http request is only working on some of the endpoints.
someService.ts
public test(q: string): Observable<any> {
// api-1 cancelling
return this.http.get<any>('http://localhost:8080/api/geosuggestion?q=' + q);
// api-2 not cancelling
// return this.http.get<any>('http://localhost:8080/api/items?q=' + q, { headers: { 'auth-token': this.authService.getToken() } });
}
Similar questions always origin from the fact that they used different obsersvable chains. In my case there has to be a different reason as i'm using the exact same logic in both cases and only replace the endpoint url.
api-1 (successfully cancelling)
api-2 (not cancelling)
Why is switchMap cancellation only working on some of my endpoints?

Related

How To guarantee that the input of the smart contract is not manipulated?

Let's say that my DApp got the following (smart) contract:
module.exports = {
winner: async function(value) {
if (value===10) {
}
}
}
Now the Dapp user can do someting which invoke the contract with some value which can be 10 or not. The Dapp determines if value equals 10 or not. So far so good.
But now it seems that anyone with a valid secret (and some XAS send to the Dapps's side chain) can invoke the contract with a simple PUT request to api/<dappId>//transactions/unsigned with value set to whatever they want.
How to ensure that the value of value is set by the Dapp and can not be manipulated?
As far as i do understand Asch DApps run on a express server, with the cors middleware enabled, which means that anyone can do a request (GET, POST, PUT, etc ) from anywhere.
So one can invoke your contract easily with a script like that shown below:
const axios = require('axios');
var fee = '10000000'
var data = {
secret: "<your secret>",
fee: fee,
type: 1001, //the number for contractfile.function
args: 1000 // a very high score
}
axios.put('http://<domain>:4096/api/dapps/<dappid>/transactions/unsigned',data)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
Due to the above it is not possible to guarantee that in input is not manipulated (send from outside the DApp). Also see: https://github.com/AschPlatform/asch/issues/228

How to make sure that one Saga completes before the other?

I'm a noob in redux-sagas, so please bear with me if I miss out something obvious!
I have a scenario wherein I'm using redux-saga to fetch an access_token from an OIDC provider and store it in the browser's localStorage.
I also use Sagas to fetch some data from an API endpoint.
But I've been experiencing problems with this approach because the Saga calling the external API gets invoked before the Auth Saga can resolve with an access_token.
My Auth Saga :
export function * handleFetchTokens () {
try {
const token = yield cps(getToken)
localStorage.setItem('token', token)
const isAuthenticated = !!(token)
yield put(actions.checkAuthSuccess(isAuthenticated))
} catch (e) {
yield put(actions.checkAuthFailure(e))
}
}
export default function * sagas () {
yield fork(takeLatest, actions.CHECK_AUTH, handleFetchTokens)
}
My API Saga :
export function * handleFetchItems () {
try {
const response = yield call(getItems)
yield put(actions.fetchItemsSuccess(response))
} catch (e) {
yield put(actions.fetchItemsFailure(e.errors))
}
}
export default function * sagas () {
yield fork(takeLatest, actions.FETCH_ITEMS, handleFetchItems)
}
My root Saga :
export default function * root () {
yield fork(items.sagas)
yield fork(authentication.sagas)
}
What should be the proper way of overcoming this problem?
Personally, I'd make sure the token is received before allowing any part of my app to actually call the FETCH_ITEMS action. Assuming you don't want to introduce such logic you will have to decide what to do with FETCH_ITEMS actions before you get the token.
The easiest approach would be to just ignore them, but that also probably isn't the most feasible way to go.
So what remains is to buffer the FETCH_ITEMS actions. You can do this using actionChannel. Since you are using takeLatest you will also want to define a sliding buffer of size 1.
It could look ruffly like this:
export default function * sagas () {
const chan = yield actionChannel(actions.FETCH_ITEMS, buffers.sliding(1))
yield take('TOKEN_RECEIVED') // wait for action informing us token was received
chan.close()
yield fork(takeLatest, chan, handleFetchItems)
yield fork(takeLatest, actions.FETCH_ITEMS, handleFetchItems)
}
More about actionChannels here https://redux-saga.js.org/docs/advanced/Channels.html
Another approach - with a bit less writing but also a bit less control - instead of buffering is to wait in the fetching saga itself:
export function * handleFetchItems () {
while (!token) yield take('TOKEN_RECEIVED');
...
}
Either way, both ways rely on waiting for a TOKEN_RECEIVED action you need to dispatch once the token is received.

Chaining RxJS Observables with interval

my first question to the community out here!
i'm working on an app which does communicates to the API in the following way
step1: create request options, add request payload --> Post request to API
API responds with a request ID
Step2: update request options, send request ID as payload --> post request to API
final response: response.json
Now the final response can take a bit of time, depending on the data requested.
this can take from anywhere between 4 to 20 seconds on an average.
How do i chain these requests using observables, i've tried using switchmap and failed (as below) but not sure how do i add a interval?
Is polling every 4 second and unsubscribing on response a viable solution? how's this done in the above context?
Edit1:
End goal: i'm new to angular and learning observables, and i'm looking to understand what is the best way forward.. does chaining observable help in this context ? i.e after the initial response have some sort of interval and use flatMap
OR use polling with interval to check if report is ready.
Here's what i have so far
export class reportDataService {
constructor(private _http: Http) { }
headers: Headers;
requestoptions: RequestOptions;
payload: any;
currentMethod: string;
theCommonBits() {
//create the post request options
// headers, username, endpoint
this.requestoptions = new RequestOptions({
method: RequestMethod.Post,
url: url,
headers: newheaders,
body: JSON.stringify(this.payload)
})
return this.requestoptions;
}
// report data service
reportService(payload: any, method: string): Observable<any> {
this.payload = payload;
this.currentMethod = method;
this.theCommonBits();
// fetch data
return this._http.request(new Request(this.requestoptions))
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
in my component
fetchData() {
this._reportService.reportService(this.payload, this.Method)
.switchMap(reportid => {
return this._reportService.reportService(reportid, this.newMethod)
}).subscribe(
data => {
this.finalData = data;
console.info('observable', this.finalData)
},
error => {
//console.error("Error fetcing data!");
return Observable.throw(error);
}
);
}
What about using Promise in your service instead of Observable, and the .then() method in the component. You can link as much .then() as you want to link actions between them.

Observing Store State Changes in Middleware

I'm writing a piece of Redux Middleware which is responsbile for adding the user's OAuth AccessToken to API_CALL cations before they hit the redux-api-middleware.
// sign appends the `Authorization` HTTP Header to an API_CALL action
function sign(action) {
action[CALL_API].headers = {
...action[CALL_API].headers,
Authorization: `Bearer ${getState()auth.accessToken}`;
}
}
// Redux middleware signature.
return ({dispatch, getState}) => {
return next => action => {
if (action[CALL_API]) {
sign(action);
}
return next(action);
}
}
However, I also want this middleware to detect when the User's AccesToken has expired...
function tokenExpired() {
return (Date.now() > getState().auth.expirationTime);
}
When this happens, the middleware detains the action (prevents it from being passed to the next middleware in the chain) and stores it in an internal list. It then kicks off the async. Token refresh process by dispatching a 'refresh access token' FSA:
if (tokenExpired()) {
// detainActions is an array, declared outside
// of the middleware's scope.
detainActions.push(action);
dispatch(refreshAccessToken());
}
else {
next(sign(action));
}
Finally, I want to listen for when the 'refresh access token' flow has completed and flush (re-dispatch) all detained actions. Currently I am doing this by looking out for AUTHENTICATION_RESPONSE FSA's as they flow through my middleware (the AUTHENTICATION_RESPONSE action is dispatched as as side-effect of the refreshAccessToken thunk.
// Redux middleware signature.
return ({dispatch, getState}) => {
return next => action => {
if (action.type === AUTHENTICATION_RESPONSE && !action.error) {
// Let the AuthResponse action pass to the store.
next(action);
// Flush detained actions now we have a new grant.
return flushAndRedispatchDetainedActions(dispatch);
}
else {
// Sign CALL_API requests logic as above.
}
}
}
However I am not happy with this approach as there is no certainty that the AUTHENTICATION_RESPONSE FSA will actually hit the reducers (it may be intercepted by other middleware, or be further defered).
Possible alternative approaches I have considered are having the refreshAccessToken actionCreator return a thunk which returns a Promise; that way my middleware can wait for that promise to resolve before flushing and replaying all requests, ie:
if (tokenExpired()) {
// refreshAccessToken thunk returns a Promise.
dispatch(refreshAccessToken());
.then(flushAndRedispatchDetainedActions();
}
Or alternativley I could have my middleware observe the store directly and trigger an action when the auth.accessToken value changes - however, I'm not clear on what the guidance is for middleware observing the store (I'm guessing it's not possible as middleware needs to be instantiated before the final store object is created.)
Thanks :)
Update
Thinking about the problem on the way home; if I were to move the actual authentication logic out of refreshAccessToken (a thunk'd action creator), and into the middleware itself then I would save a lot of pain:
// Redux middleware signature.
return ({dispatch, getState}) => {
return next => action => {
if (action[CALL_AUTH]) {
authHelper.refreshGrant()
.then(grant => dispatch(processGrant(newGrant));
}
else {
// Sign CALL_API requests logic as above.
}
}
}

Play2 async when using action composition

In Play2, I understand the concepts of action composition and using Async {...} for asynchronous responses, but I've not seen an example of these approaches used together.
To be clear, say you're using action composition to ensure that a user is authenticated:
def index = Authenticated { user =>
Action { request =>
Async {
Ok("Hello " + user.name)
}
}
}
In the implementation of Authenticated, if we assume that this a DB is being looked up to retrieve a user, then it appears to me that this part would be a blocking call, leaving only the response within the Action body as non-blocking.
Can somebody explain how I can do non-blocking async I/O that encompasses the authentication part as well?
My solution has been to compose actions inside out, like so:
def index = Action { request =>
Async {
Authenticated { user =>
Ok("Hello " + user.name)
}
}
}
My Authenticated signature would then look something like:
def Authenticated(body: => Result): Result = {
// authenticate, and then
body
}
The downside here is that body parsing will occur before authentication, which may or may not be an issue for you.
I can give a full example: http://pastebin.com/McHaqrFv
The essence of it is:
def WithAuthentication(f: WithAuthentication => Result) = Action {
implicit request => AsyncResult {
// async auth logic goes here
}
}
In controllers simply:
def indexAction = WithAuthentication {
implicit request =>
Ok(views.html.index())
}
or even:
def someAction = WithAuthentication {
implicit request => Async {
// more async logic here
}
}
It's a template-friendly solution, feel free to use it. Maybe sometimes i'll create a plugin from it. Just coded for my application, so far it seems working.

Resources