Skip to content

[typescript-angular2] Allow lazy oauth token refresh (#6486) #6496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export class {{classname}} {


{{^useHttpClient}}
{{! not sure why we used to generate a second method here rather than inlining those few lines of code,
but let's keep it for now for the sake of backwards compatiblity. }}
{{! not sure why we used to generate a second method here rather than inlining those few lines of code,
but let's keep it for now for the sake of backwards compatiblity. }}
{{#operation}}
/**
* {{&notes}}
Expand Down Expand Up @@ -152,17 +152,17 @@ export class {{classname}} {
{{/isListContainer}}
{{/queryParams}}

{{/hasQueryParams}}
let headers = {{#useHttpClient}}this.defaultHeaders;{{/useHttpClient}}{{^useHttpClient}}new Headers(this.defaultHeaders.toJSON()); // https://github.com/angular/angular/issues/6845{{/useHttpClient}}
{{/hasQueryParams}}
let headersObservable = Observable.of({{#useHttpClient}}this.defaultHeaders{{/useHttpClient}}{{^useHttpClient}}new Headers(this.defaultHeaders.toJSON()){{/useHttpClient}});
{{#headerParams}}
{{#isListContainer}}
if ({{paramName}}) {
{{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
headersObservable = headersObservable.{{#useHttpClient}}map((headers: HttpHeaders) => { return {{/useHttpClient}}{{^useHttpClient}}do((headers: Headers) => { {{/useHttpClient}}headers.set('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])); });
}
{{/isListContainer}}
{{^isListContainer}}
if ({{paramName}} !== undefined && {{paramName}} !== null) {
{{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{baseName}}', String({{paramName}}));
headersObservable = headersObservable.{{#useHttpClient}}map((headers: HttpHeaders) => { return {{/useHttpClient}}{{^useHttpClient}}do((headers: Headers) => { {{/useHttpClient}}headers.set('{{baseName}}', String({{paramName}})); });
}
{{/isListContainer}}
{{/headerParams}}
Expand All @@ -172,7 +172,7 @@ export class {{classname}} {
{{#isApiKey}}
{{#isKeyInHeader}}
if (this.configuration.apiKeys["{{keyParamName}}"]) {
{{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]);
headersObservable = headersObservable.{{#useHttpClient}}map((headers: HttpHeaders) => { return {{/useHttpClient}}{{^useHttpClient}}do((headers: Headers) => { {{/useHttpClient}}headers.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]); });
}

{{/isKeyInHeader}}
Expand All @@ -185,23 +185,26 @@ export class {{classname}} {
{{/isApiKey}}
{{#isBasic}}
if (this.configuration.username || this.configuration.password) {
{{#useHttpClient}}headers = {{/useHttpClient}}headers.set('Authorization', 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password));
headersObservable = headersObservable.{{#useHttpClient}}map((headers: HttpHeaders) => { return {{/useHttpClient}}{{^useHttpClient}}do((headers: Headers) => { {{/useHttpClient}}headers.set('Authorization', 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password)); });
}

{{/isBasic}}
{{#isOAuth}}
if (this.configuration.accessToken) {
let accessToken = typeof this.configuration.accessToken === 'function'
? this.configuration.accessToken()
: this.configuration.accessToken;
{{#useHttpClient}}headers = {{/useHttpClient}}headers.set('Authorization', 'Bearer ' + accessToken);
let accessTokenObservable = typeof this.configuration.accessToken === 'function'
? this.configuration.accessToken("{{name}}", [{{#scopes}}"{{{scope}}}"{{^-last}}, {{/-last}}{{/scopes}}])
: Observable.of(this.configuration.accessToken);
headersObservable = headersObservable.zip(accessTokenObservable, (headers: {{#useHttpClient}}Http{{/useHttpClient}}Headers, accessToken: string) => {
{{#useHttpClient}}return {{/useHttpClient}}headers.set('Authorization', 'Bearer ' + accessToken);{{^useHttpClient}}
return headers;{{/useHttpClient}}
});
}

{{/isOAuth}}
{{/authMethods}}
{{#bodyParam}}
{{^useHttpClient}}
headers.set('Content-Type', 'application/json');
headersObservable = headersObservable.do((headers: Headers) => headers.set('Content-Type', 'application/json'));

{{/useHttpClient}}
{{/bodyParam}}
Expand Down Expand Up @@ -235,7 +238,7 @@ export class {{classname}} {
convertFormParamsToString = true;
formParams = new URLSearchParams('', new CustomQueryEncoderHelper());
// set the content-type explicitly to avoid having it set to 'text/plain'
headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
headersObservable = headersObservable.do((headers: Headers) => headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8'));
{{/useHttpClient}}
}

Expand Down Expand Up @@ -263,8 +266,8 @@ export class {{classname}} {

{{/hasFormParams}}
{{#useHttpClient}}
return this.httpClient.{{httpMethod}}{{^isResponseFile}}<any>{{/isResponseFile}}(`${this.basePath}{{{path}}}`, {{#bodyParam}}{{paramName}}, {{/bodyParam}}
{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams, {{/hasFormParams}}{
return headersObservable.mergeMap((headers: HttpHeaders) => this.httpClient.{{httpMethod}}{{^isResponseFile}}<any>{{/isResponseFile}}(`${this.basePath}{{{path}}}`, {{#bodyParam}}{{paramName}}, {{/bodyParam}}
{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams, {{/hasFormParams}}{
{{#hasQueryParams}}
params: queryParameters,
{{/hasQueryParams}}
Expand All @@ -273,33 +276,32 @@ export class {{classname}} {
responseType: "blob",
{{/isResponseFile}}
withCredentials: this.configuration.withCredentials,
});
}));
{{/useHttpClient}}
{{^useHttpClient}}
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: {{httpMethod}},
headers: headers,
let requestOptionsObservable = headersObservable.map((headers: Headers) => {
let requestOptions: RequestOptionsArgs = new RequestOptions({
method: {{httpMethod}},
headers: headers,
{{#bodyParam}}
body: {{paramName}} == null ? '' : JSON.stringify({{paramName}}), // https://github.com/angular/angular/issues/10612
body: {{paramName}} == null ? '' : JSON.stringify({{paramName}}), // https://github.com/angular/angular/issues/10612
{{/bodyParam}}
{{#hasFormParams}}
body: convertFormParamsToString ? formParams.toString() : formParams,
body: convertFormParamsToString ? formParams.toString() : formParams,
{{/hasFormParams}}
{{#isResponseFile}}
responseType: ResponseContentType.Blob,
responseType: ResponseContentType.Blob,
{{/isResponseFile}}
{{#hasQueryParams}}
search: queryParameters,
search: queryParameters,
{{/hasQueryParams}}
withCredentials:this.configuration.withCredentials
withCredentials:this.configuration.withCredentials
});
return requestOptions;
});
// https://github.com/swagger-api/swagger-codegen/issues/4037
if (extraHttpRequestParams) {
requestOptions = (<any>Object).assign(requestOptions, extraHttpRequestParams);
}

return this.http.request(`${this.basePath}{{{path}}}`, requestOptions);
{{/useHttpClient}}
return requestOptionsObservable.mergeMap((requestOptions: RequestOptionsArgs) => this.http.request(`${this.basePath}{{{path}}}`, requestOptions));
{{/useHttpClient}}
}

{{/operation}}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Observable } from 'rxjs/Observable';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | (() => string);
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;
}
Expand All @@ -11,7 +13,7 @@ export class Configuration {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | (() => string);
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@

// Statics
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/of';

// Operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/zip';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/mergeMap';
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,7 @@
<module>samples/client/petstore/typescript-jquery/npm</module>-->
<module>samples/client/petstore/typescript-angular-v2/npm</module>
<module>samples/client/petstore/typescript-angular-v4/npm</module>
<module>samples/client/petstore/typescript-angular-v4.3/npm</module>
<!-- comment out due to https://github.com/swagger-api/swagger-codegen/issues/6658
<module>samples/client/petstore/swift3/default/SwaggerClientTests</module>
<module>samples/client/petstore/swift3/promisekit/SwaggerClientTests</module>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
wwwroot/*.js
node_modules
typings
dist
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.3
2.3.0-SNAPSHOT
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import * as api from './api/api';
import * as angular from 'angular';
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { Configuration } from './configuration';

const apiModule = angular.module('api', [])
.service('FakeApi', api.FakeApi)
import { FakeService } from './api/fake.service';

export default apiModule;
@NgModule({
imports: [ CommonModule, HttpModule ],
declarations: [],
exports: [],
providers: [ FakeService ]
})
export class ApiModule {
public static forConfig(configurationFactory: () => Configuration): ModuleWithProviders {
return {
ngModule: ApiModule,
providers: [ {provide: Configuration, useFactory: configurationFactory}]
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './FakeApi';
import { FakeApi } from './FakeApi';
export const APIS = [FakeApi];
export * from './fake.service';
import { FakeService } from './fake.service';
export const APIS = [FakeService];
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Swagger Petstore *_/ ' \" =end -- \\r\\n \\n \\r
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
*
* OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r
* Contact: apiteam@swagger.io *_/ ' \" =end -- \\r\\n \\n \\r
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/

/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import '../rxjs-operators';


import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';
import { CustomHttpUrlEncodingCodec } from '../encoder';


@Injectable()
export class FakeService {

protected basePath = 'https://petstore.swagger.io *_/ ' \" =end -- \\r\\n \\n \\r/v2 *_/ ' \" =end -- \\r\\n \\n \\r';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();

constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
if (basePath) {
this.basePath = basePath;
}
if (configuration) {
this.configuration = configuration;
this.basePath = basePath || configuration.basePath || this.basePath;
}
}

/**
* @param consumes string[] mime-types
* @return true: consumes contains 'multipart/form-data', false: otherwise
*/
private canConsumeForm(consumes: string[]): boolean {
const form = 'multipart/form-data';
for (let consume of consumes) {
if (form === consume) {
return true;
}
}
return false;
}



/**
* To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
*
* @param test code inject * &#39; &quot; &#x3D;end rn n r To test code injection *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
*/
public testCodeInjectEndRnNR(test code inject * &#39; &quot; &#x3D;end rn n r?: string): Observable<{}> {

let headersObservable = Observable.of(this.defaultHeaders);

// to determine the Content-Type header
let consumes: string[] = [
'application/json',
'*_/ =end -- '
];
const canConsumeForm = this.canConsumeForm(consumes);

let formParams: { append(param: string, value: any): void; };
let useForm = false;
let convertFormParamsToString = false;
if (useForm) {
formParams = new FormData();
} else {
formParams = new HttpParams({encoder: new CustomHttpUrlEncodingCodec()});
}



if (test code inject * &#39; &quot; &#x3D;end rn n r !== undefined) {
formParams = formParams.append('test code inject */ &#39; &quot; &#x3D;end -- \r\n \n \r', <any>test code inject * &#39; &quot; &#x3D;end rn n r) || formParams;
}

return headersObservable.mergeMap((headers: HttpHeaders) => this.httpClient.put<any>(`${this.basePath}/fake`,
convertFormParamsToString ? formParams.toString() : formParams, {
headers: headers,
withCredentials: this.configuration.withCredentials,
}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Observable } from 'rxjs/Observable';

export interface ConfigurationParameters {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;
}

export class Configuration {
apiKeys?: {[ key: string ]: string};
username?: string;
password?: string;
accessToken?: string | ((name: string, scopes?: string[]) => Observable<string>);
basePath?: string;
withCredentials?: boolean;

constructor(configurationParameters: ConfigurationParameters = {}) {
this.apiKeys = configurationParameters.apiKeys;
this.username = configurationParameters.username;
this.password = configurationParameters.password;
this.accessToken = configurationParameters.accessToken;
this.basePath = configurationParameters.basePath;
this.withCredentials = configurationParameters.withCredentials;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { HttpUrlEncodingCodec } from '@angular/common/http';

/**
* CustomHttpUrlEncodingCodec
* Fix plus sign (+) not encoding, so sent as blank space
* See: https://github.com/angular/angular/issues/11058#issuecomment-247367318
*/
export class CustomHttpUrlEncodingCodec extends HttpUrlEncodingCodec {
encodeKey(k: string): string {
k = super.encodeKey(k);
return k.replace(/\+/gi, '%2B');
}
encodeValue(v: string): string {
v = super.encodeValue(v);
return v.replace(/\+/gi, '%2B');
}
}

Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from './api/api';
export * from './model/models';
export * from './model/models';
export * from './variables';
export * from './configuration';
export * from './api.module';
Loading