ngx-restangular icon indicating copy to clipboard operation
ngx-restangular copied to clipboard

Enhance support for getMethodOverride in getList function

Open chander opened this issue 5 years ago • 3 comments

The ability to perform GET-as-POST using the overrideMethods functionality of restangular is very useful; however it's only implemented partially.

One of the common use cases with GET as POST is to have a payload that is too large to be passed in as part of the URL's GET querystring. Using POST instead allows the request to bypass these restrictions, and the need to change settings on servers such as Nginx to support what might ab absurdly long URL.

This issue was identified and corrected by @SamanthaAdrichem some time ago - but was (for whatever reason) never merged into mgonto's Restangular branch.

The fix is referenced in a PR here:

https://github.com/SamanthaAdrichem/restangular/commit/cc03340b0be428ea9c0f75bf34eb453743b7fb0d

and in a ticket here: https://github.com/mgonto/restangular/issues/1329

Adding in the functionality would allow GET-as-POST to also send the Payload in the POST body, instead of in the querystring.

chander avatar Mar 15 '20 18:03 chander

Hey. My Solution is for AngularJs not for Angular.

For Angular we actually no longer use Restangular. We added a request interceptor to convert all gets to the override posts

import {HttpEvent, HttpHandler, HttpInterceptor, HttpParams, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {LibString} from 'src/app/core/lib/string';

@Injectable()
export class GetAsPostInterceptor implements HttpInterceptor {

	public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
		if (
			request.url
			&& LibString.startsWith(request.url, '/api')
			&& request.method
			&& request.method.toUpperCase() === 'GET'
		) {
			let body: {[key: string]: any} = {};
			request.params.keys().map((paramName: string) => {
				body[paramName] = request.params.getAll(paramName);
				body[paramName] = body[paramName].length === 1 ? body[paramName].pop() : body[paramName];
			});
			request = request.clone({
				method: 'POST',
				setHeaders: {
					'X-HTTP-Method-Override': request.method
				},
				params: new HttpParams(),
				body: body
			});
		}
		return next.handle(request);
	}
}

and in app.module.ts

import {GetAsPostInterceptor} from '.../get-as-post.interceptor';

@NgModule({
	exports: [
	],
	imports: [
	],
	// All providers you need in AngularJS
	providers: [
		// Request interceptors, might be able to move them to the actual modules, but those are generated
		{ provide: HTTP_INTERCEPTORS, useClass: GetAsPostInterceptor, multi: true },
	]
})
export class AppModule implements DoBootstrap {
}

LibString

export class LibString {

	public static startsWith(inputString: string, prefix: string): boolean {
		return inputString.indexOf(prefix) === 0;
	}
}

(edit) Only bug it has now is that if you add an array of [0] it's perceived as empty 🤷‍♀ didn't have time to fix it.

SamanthaAdrichem avatar Mar 15 '20 18:03 SamanthaAdrichem

To be clear, ngx-Restangular is an angular component, and I believe that the change you made to Angular's Restangular is relevant here (thanks for that!)

The fact that your application doesn't use ngx-restangular (which is the Angular version of Restangular) is not really relevant - others do use ngx-restangular, and the fix/change is relevant to them.

thanks

chander avatar Mar 15 '20 19:03 chander

Yeah, I understand, but as I said my pull request is on the AngularJS version. Hope they will implement it for you in the Angular version

SamanthaAdrichem avatar Mar 15 '20 19:03 SamanthaAdrichem