├── src
├── assets
│ ├── .gitkeep
│ └── calculator.wsdl
├── app
│ ├── app.component.css
│ ├── app.component.spec.ts
│ ├── app.module.ts
│ ├── app.component.ts
│ └── app.component.html
├── favicon.ico
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── styles.css
├── tsconfig.app.json
├── tsconfig.spec.json
├── tslint.json
├── main.ts
├── index.html
├── test.ts
├── karma.conf.js
└── polyfills.ts
├── projects
└── ngx-soap
│ ├── tsconfig.lib.prod.json
│ ├── src
│ ├── public_api.ts
│ ├── lib
│ │ ├── soap
│ │ │ ├── security
│ │ │ │ ├── templates
│ │ │ │ │ ├── wsse-security-token.ejs
│ │ │ │ │ └── wsse-security-header.ejs
│ │ │ │ ├── security.ts
│ │ │ │ ├── BearerSecurity.ts
│ │ │ │ ├── BasicAuthSecurity.ts
│ │ │ │ ├── NTLMSecurity.ts
│ │ │ │ ├── ClientSSLSecurityPFX.js
│ │ │ │ ├── ClientSSLSecurity.js
│ │ │ │ ├── WSSecurity.ts
│ │ │ │ └── WSSecurityCert.ts
│ │ │ ├── utils.ts
│ │ │ ├── soapAttachment.ts
│ │ │ ├── multipart.ts
│ │ │ ├── soap.ts
│ │ │ ├── http.ts
│ │ │ ├── interfaces.ts
│ │ │ ├── nscontext.ts
│ │ │ ├── _soap.d.ts
│ │ │ └── client.ts
│ │ ├── ngx-soap.module.ts
│ │ ├── ngx-soap.service.ts
│ │ └── ngx-soap.service.spec.ts
│ └── test.ts
│ ├── ng-package.prod.json
│ ├── ng-package.json
│ ├── tsconfig.spec.json
│ ├── tslint.json
│ ├── tsconfig.lib.json
│ ├── package.json
│ ├── karma.conf.js
│ └── README.md
├── .gitignore
├── proxy.conf.json
├── e2e
├── src
│ ├── app.po.ts
│ └── app.e2e-spec.ts
├── tsconfig.e2e.json
└── protractor.conf.js
├── .browserslistrc
├── tsconfig.json
├── LICENSE
├── README.md
├── CHANGELOG.md
├── package.json
├── tslint.json
└── angular.json
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lula/ngx-soap/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | body { margin: 0; }
4 |
--------------------------------------------------------------------------------
/projects/ngx-soap/tsconfig.lib.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.lib.json",
3 | "angularCompilerOptions": {
4 | "enableIvy": false
5 | }
6 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | coverage
4 | yarn.lock
5 | .vscode
6 | .idea
7 | *.iml
8 | tools/bin
9 | tools/test
10 | dist
11 | spec/out
--------------------------------------------------------------------------------
/projects/ngx-soap/src/public_api.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API Surface of ngx-soap
3 | */
4 |
5 | export * from './lib/ngx-soap.service';
6 | export * from './lib/ngx-soap.module';
7 |
--------------------------------------------------------------------------------
/proxy.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "/calculator": {
3 | "target": "http://www.dneonline.com",
4 | "secure": false,
5 | "changeOrigin": "true",
6 | "pathRewrite": {"^/calculator": ""}
7 | }
8 | }
--------------------------------------------------------------------------------
/projects/ngx-soap/ng-package.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/ngx-soap",
4 | "lib": {
5 | "entryFile": "src/public_api.ts"
6 | }
7 | }
--------------------------------------------------------------------------------
/projects/ngx-soap/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/ngx-soap",
4 | "deleteDestPath": false,
5 | "lib": {
6 | "entryFile": "src/public_api.ts"
7 | }
8 | }
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/templates/wsse-security-token.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/ngx-soap.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { HttpClientModule } from '@angular/common/http';
3 |
4 | @NgModule({
5 | imports: [
6 | HttpClientModule
7 | ],
8 | exports: []
9 | })
10 | export class NgxSoapModule { }
11 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "types": []
6 | },
7 | "files": [
8 | "main.ts",
9 | "polyfills.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/projects/ngx-soap/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts"
12 | ],
13 | "include": [
14 | "**/*.spec.ts",
15 | "**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "test.ts",
12 | "polyfills.ts"
13 | ],
14 | "include": [
15 | "**/*.spec.ts",
16 | "**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('workspace-project App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to app!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | # For IE 9-11 support, please uncomment the last line of the file and adjust as needed
5 | > 0.5%
6 | last 2 versions
7 | Firefox ESR
8 | not dead
9 | # IE 9-11
--------------------------------------------------------------------------------
/projects/ngx-soap/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | // "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "lib",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "lib",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.log(err));
13 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/security.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { BasicAuthSecurity } from './BasicAuthSecurity';
4 | import { WSSecurity } from './WSSecurity';
5 | // import { WSSecurityCert } from './WSSecurityCert';
6 | import { BearerSecurity } from './BearerSecurity';
7 | import { NTLMSecurity } from './NTLMSecurity';
8 |
9 | export const security = {
10 | BasicAuthSecurity,
11 | BearerSecurity,
12 | WSSecurity,
13 | // WSSecurityCert,
14 | NTLMSecurity,
15 | // ClientSSLSecurity,
16 | // ClientSSLSecurityPFX
17 | };
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | NgxSoapLib
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/BearerSecurity.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // var _ = require('lodash');
4 | import * as _ from 'lodash';
5 |
6 | export function BearerSecurity(token, defaults) {
7 | this._token = token;
8 | this.defaults = {};
9 | _.merge(this.defaults, defaults);
10 | }
11 |
12 | BearerSecurity.prototype.addHeaders = function(headers) {
13 | headers.Authorization = "Bearer " + this._token;
14 | };
15 |
16 | BearerSecurity.prototype.toXML = function() {
17 | return '';
18 | };
19 |
20 | BearerSecurity.prototype.addOptions = function(options) {
21 | _.merge(options, this.defaults);
22 | };
23 |
24 | // module.exports = BearerSecurity;
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "downlevelIteration": true,
6 | "module": "es2020",
7 | "outDir": "./dist/out-tsc",
8 | "sourceMap": true,
9 | "declaration": false,
10 | "moduleResolution": "node",
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "target": "es2015",
14 | "typeRoots": [
15 | "node_modules/@types"
16 | ],
17 | "lib": [
18 | "es2017",
19 | "dom"
20 | ],
21 | "paths": {
22 | "ngx-soap": [
23 | "dist/ngx-soap"
24 | ],
25 | "ngx-soap/*": [
26 | "dist/ngx-soap/*"
27 | ]
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * In development mode, to ignore zone related error stack frames such as
11 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
12 | * import the following file, but please comment it out in production mode
13 | * because it will have performance impact when throw error
14 | */
15 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
16 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/BasicAuthSecurity.ts:
--------------------------------------------------------------------------------
1 | import * as _ from 'lodash';
2 | import { Buffer } from 'buffer';
3 |
4 | export function BasicAuthSecurity(username, password, defaults) {
5 | this._username = username;
6 | this._password = password;
7 | this.defaults = {};
8 | _.merge(this.defaults, defaults);
9 | }
10 |
11 | BasicAuthSecurity.prototype.addHeaders = function(headers) {
12 | headers.Authorization = 'Basic ' + new Buffer((this._username + ':' + this._password) || '').toString('base64');
13 | };
14 |
15 | BasicAuthSecurity.prototype.toXML = function() {
16 | return '';
17 | };
18 |
19 | BasicAuthSecurity.prototype.addOptions = function(options) {
20 | _.merge(options, this.defaults);
21 | };
22 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'core-js/es7/reflect';
4 | import 'zone.js/dist/zone';
5 | import 'zone.js/dist/zone-testing';
6 | import { getTestBed } from '@angular/core/testing';
7 | import {
8 | BrowserDynamicTestingModule,
9 | platformBrowserDynamicTesting
10 | } from '@angular/platform-browser-dynamic/testing';
11 |
12 | declare const require: any;
13 |
14 | // First, initialize the Angular testing environment.
15 | getTestBed().initTestEnvironment(
16 | BrowserDynamicTestingModule,
17 | platformBrowserDynamicTesting()
18 | );
19 | // Then we find all the tests.
20 | const context = require.context('./', true, /\.spec\.ts$/);
21 | // And load the modules.
22 | context.keys().map(context);
23 |
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './src/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: require('path').join(__dirname, './tsconfig.e2e.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/ngx-soap.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { createClient } from './soap/soap';
3 | import { HttpClient } from '@angular/common/http';
4 | import { Client } from './soap/interfaces';
5 |
6 | export {
7 | Client,
8 | WSDL,
9 | ISoapMethod,
10 | ISoapMethodResponse,
11 | BasicAuthSecurity,
12 | BearerSecurity,
13 | // WSSecurityCert,
14 | WSSecurity,
15 | NTLMSecurity
16 | } from './soap/interfaces';
17 |
18 | export { security } from './soap/security/security'
19 |
20 | @Injectable({
21 | providedIn: 'root'
22 | })
23 | export class NgxSoapService {
24 |
25 | constructor(private http: HttpClient) { }
26 |
27 | createClient(wsdlUrl: string, options: any = {}, endpoint?: string): Promise {
28 | options.httpClient = this.http;
29 | return createClient(wsdlUrl, options, endpoint);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/utils.ts:
--------------------------------------------------------------------------------
1 | import sha1 from 'crypto-js/sha1';
2 | import Base64 from 'crypto-js/enc-base64';
3 | import { Buffer } from 'buffer';
4 |
5 | export const passwordDigest = function passwordDigest(nonce, created, password) {
6 | const rawNonce = new Buffer(nonce || '', 'base64').toString('binary');
7 | return Base64.stringify(sha1(rawNonce + created + password, ''));
8 | };
9 |
10 | export const TNS_PREFIX = '__tns__'; // Prefix for targetNamespace
11 |
12 | /**
13 | * Find a key from an object based on the value
14 | * @param Namespace prefix/uri mapping
15 | * @param nsURI value
16 | * @returns The matching key
17 | */
18 | export const findPrefix = function(xmlnsMapping, nsURI) {
19 | for (const n in xmlnsMapping) {
20 | if (n === TNS_PREFIX) { continue; }
21 | if (xmlnsMapping[n] === nsURI) {
22 | return n;
23 | }
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/NTLMSecurity.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // var _ = require('lodash');
4 | import * as _ from 'lodash';
5 |
6 | export function NTLMSecurity(username, password, domain, workstation) {
7 | if (typeof username === "object") {
8 | this.defaults = username;
9 | this.defaults.ntlm = true;
10 | } else {
11 | this.defaults = {
12 | ntlm: true,
13 | username: username,
14 | password: password,
15 | domain: domain,
16 | workstation: workstation
17 | };
18 | }
19 | }
20 |
21 | NTLMSecurity.prototype.addHeaders = function (headers) {
22 | headers.Connection = 'keep-alive';
23 | };
24 |
25 | NTLMSecurity.prototype.toXML = function () {
26 | return '';
27 | };
28 |
29 | NTLMSecurity.prototype.addOptions = function (options) {
30 | _.merge(options, this.defaults);
31 | };
32 |
33 | // module.exports = NTLMSecurity;
34 |
--------------------------------------------------------------------------------
/projects/ngx-soap/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/lib",
5 | "target": "es2015",
6 | "module": "es2015",
7 | "moduleResolution": "node",
8 | "declaration": true,
9 | "sourceMap": true,
10 | "inlineSources": true,
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "importHelpers": true,
14 | "types": [],
15 | "lib": [
16 | "dom",
17 | "es2015"
18 | ]
19 | },
20 | "angularCompilerOptions": {
21 | "skipTemplateCodegen": true,
22 | "strictMetadataEmit": true,
23 | "fullTemplateTypeCheck": true,
24 | "strictInjectionParameters": true,
25 | "flatModuleId": "AUTOGENERATED",
26 | "flatModuleOutFile": "AUTOGENERATED"
27 | },
28 | "exclude": [
29 | "src/test.ts",
30 | "**/*.spec.ts"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/templates/wsse-security-header.ejs:
--------------------------------------------------------------------------------
1 |
4 | <%-binaryToken%>
8 |
9 | <%-created%>
10 | <%-expires%>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/projects/ngx-soap/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-soap",
3 | "version": "0.7.0",
4 | "description": "SOAP service for Angular",
5 | "homepage": "https://github.com/lula/ngx-soap",
6 | "author": "Luca Lulani",
7 | "license": "MIT",
8 | "keywords": [
9 | "Angular",
10 | "Angular2",
11 | "Angular4",
12 | "Angular5",
13 | "Angular6",
14 | "Angular7",
15 | "Angular8",
16 | "Angular9",
17 | "Angular10",
18 | "@angular",
19 | "SOAP",
20 | "WSDL"
21 | ],
22 | "dependencies": {
23 | "tslib": "^2.0.0"
24 | },
25 | "peerDependencies": {
26 | "@angular/common": ">=6.0.0 <=10.0.0",
27 | "@angular/core": ">=6.0.0 <=10.0.0",
28 | "buffer": "^5.1.0",
29 | "concat-stream": "^1.6.2",
30 | "core-js": "^2.5.4",
31 | "crypto-js": "^3.1.9-1",
32 | "events": "^3.0.0",
33 | "lodash": "^4.17.10",
34 | "rxjs": "^6.0.0",
35 | "sax": "^1.2.4",
36 | "stream": "0.0.2",
37 | "uuid": "^3.3.2"
38 | }
39 | }
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/soapAttachment.ts:
--------------------------------------------------------------------------------
1 | export class SoapAttachment {
2 |
3 | constructor(
4 | public mimetype: string,
5 | public contentId: string,
6 | public name: string,
7 | public body: any
8 | ) {
9 |
10 | }
11 |
12 | static fromFormFiles(files: FileList | File[] = []): Promise {
13 | if (files instanceof FileList) {
14 | files = Array.from(files);
15 | }
16 |
17 | const promises = files.map((file: any) => {
18 | return new Promise(function(resolve) {
19 | const reader = new FileReader();
20 | reader.readAsArrayBuffer(file);
21 | reader.onload = function (e) {
22 | const arrayBuffer = (e.target as any).result;
23 | const bytes = new Uint8Array(arrayBuffer);
24 | const attachment = new SoapAttachment(file.type, file.contentId || file.name, file.name, bytes);
25 | resolve(attachment);
26 | }
27 | });
28 | });
29 |
30 | return Promise.all(promises);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 | describe('AppComponent', () => {
4 | beforeEach(async(() => {
5 | TestBed.configureTestingModule({
6 | declarations: [
7 | AppComponent
8 | ],
9 | }).compileComponents();
10 | }));
11 | it('should create the app', async(() => {
12 | const fixture = TestBed.createComponent(AppComponent);
13 | const app = fixture.debugElement.componentInstance;
14 | expect(app).toBeTruthy();
15 | }));
16 | it(`should have as title 'app'`, async(() => {
17 | const fixture = TestBed.createComponent(AppComponent);
18 | const app = fixture.debugElement.componentInstance;
19 | expect(app.title).toEqual('app');
20 | }));
21 | it('should render title in a h1 tag', async(() => {
22 | const fixture = TestBed.createComponent(AppComponent);
23 | fixture.detectChanges();
24 | const compiled = fixture.debugElement.nativeElement;
25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
26 | }));
27 | });
28 |
--------------------------------------------------------------------------------
/projects/ngx-soap/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Luca Lulani
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | proxies: {
31 | '/calculator': {
32 | 'target': "http://www.dneonline.com",
33 | 'secure': false,
34 | 'changeOrigin': true,
35 | 'pathRewrite': {"^/calculator": ""}
36 | }
37 | }
38 | });
39 | };
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import { HttpClientModule } from '@angular/common/http';
4 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
5 | import { MatButtonModule } from '@angular/material/button';
6 | import { MatCardModule } from '@angular/material/card';
7 | import { MatFormFieldModule } from '@angular/material/form-field';
8 | import { MatInputModule } from '@angular/material/input';
9 | import { MatProgressBarModule } from '@angular/material/progress-bar';
10 | import { MatToolbarModule } from '@angular/material/toolbar';
11 | import { FormsModule } from '@angular/forms';
12 |
13 | import { NgxSoapModule } from 'ngx-soap';
14 | import { AppComponent } from './app.component';
15 | import { FlexLayoutModule } from '@angular/flex-layout';
16 |
17 | const ANGULAR_MATERIAL_MODULES = [
18 | MatToolbarModule, MatInputModule, MatButtonModule, MatCardModule,
19 | MatProgressBarModule, MatFormFieldModule
20 | ];
21 |
22 | @NgModule({
23 | declarations: [
24 | AppComponent
25 | ],
26 | imports: [
27 | BrowserModule,
28 | FormsModule,
29 | NgxSoapModule,
30 | HttpClientModule,
31 | BrowserAnimationsModule,
32 | FlexLayoutModule,
33 | ...ANGULAR_MATERIAL_MODULES
34 | ],
35 | providers: [],
36 | bootstrap: [AppComponent]
37 | })
38 | export class AppModule { }
39 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/ClientSSLSecurityPFX.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs')
4 | , https = require('https')
5 | , _ = require('lodash');
6 |
7 | /**
8 | * activates SSL for an already existing client using a PFX cert
9 | *
10 | * @module ClientSSLSecurityPFX
11 | * @param {Buffer|String} pfx
12 | * @param {String} passphrase
13 | * @constructor
14 | */
15 | function ClientSSLSecurityPFX(pfx, passphrase, defaults) {
16 | if (typeof passphrase === 'object') {
17 | defaults = passphrase;
18 | }
19 | if (pfx) {
20 | if (Buffer.isBuffer(pfx)) {
21 | this.pfx = pfx;
22 | } else if (typeof pfx === 'string') {
23 | this.pfx = fs.readFileSync(pfx);
24 | } else {
25 | throw new Error('supplied pfx file should be a buffer or a file location');
26 | }
27 | }
28 |
29 | if (passphrase) {
30 | if (typeof passphrase === 'string') {
31 | this.passphrase = passphrase;
32 | }
33 | }
34 | this.defaults = {};
35 | _.merge(this.defaults, defaults);
36 | }
37 |
38 | ClientSSLSecurityPFX.prototype.toXML = function(headers) {
39 | return '';
40 | };
41 |
42 | ClientSSLSecurityPFX.prototype.addOptions = function(options) {
43 | options.pfx = this.pfx;
44 | if (this.passphrase) {
45 | options.passphrase = this.passphrase;
46 | }
47 | _.merge(options, this.defaults);
48 | options.agent = new https.Agent(options);
49 | };
50 |
51 | module.exports = ClientSSLSecurityPFX;
52 |
--------------------------------------------------------------------------------
/projects/ngx-soap/README.md:
--------------------------------------------------------------------------------
1 | # ngx-soap
2 |
3 | Simple SOAP client for Angular 6/7 based on amazing [node-soap](https://github.com/vpulim/node-soap).
4 |
5 | Project has been recreated from scratch with Angualr 6 CLI.
6 |
7 | ## npm
8 |
9 | 1. install ngx-soap and dependencies
10 |
11 | `npm install --save ngx-soap`
12 |
13 | `npm install --save buffer concat-stream core-js crypto-js events lodash sax stream uuid`
14 |
15 | 2. Add NgxSoapModule to your app module
16 |
17 | ```
18 | import { NgxSoapModule } from 'ngx-soap';
19 | ...
20 | @NgModule({
21 | imports: [ ..., NgxSoapModule, ... ]
22 | ...
23 | ```
24 |
25 | 3. Inject NgxSoapService in your component:
26 |
27 | ```
28 | ...
29 | import { NgxSoapService, Client, ISoapMethodResponse } from 'ngx-soap';
30 | ...
31 |
32 | @Component({
33 | selector: 'app-root',
34 | templateUrl: './app.component.html',
35 | styleUrls: ['./app.component.css']
36 | })
37 | export class AppComponent {
38 | client: Client;
39 | intA = 2;
40 | intB = 3;
41 |
42 | constructor(private soap: NgxSoapService) {
43 | this.soap.createClient('assets/calculator.wsdl').subscribe(client => this.client = client);
44 | }
45 |
46 | sum() {
47 | const body = {
48 | intA: this.intA,
49 | intB: this.intB
50 | };
51 | (this.client).Add(body).subscribe((res: ISoapMethodResponse) => this.message = res.result.AddResult);
52 | }
53 | }
54 | ```
55 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/multipart.ts:
--------------------------------------------------------------------------------
1 | export class Multipart {
2 | preambleCRLF = true;
3 | postambleCRLF = true;
4 |
5 | build(parts, boundary) {
6 | const body = [];
7 |
8 | function add (part) {
9 | if (typeof part === 'number') {
10 | part = part.toString();
11 | }
12 | return body.push(part)
13 | }
14 |
15 | if (this.preambleCRLF) {
16 | add('\r\n')
17 | }
18 |
19 | parts.forEach(function (part) {
20 | let preamble = '--' + boundary + '\r\n';
21 | Object.keys(part).forEach(function (key) {
22 | if (key === 'body') { return }
23 | preamble += key + ': ' + part[key] + '\r\n'
24 | });
25 | preamble += '\r\n';
26 | add(preamble);
27 | add(part.body);
28 | add('\r\n');
29 | });
30 | add('--' + boundary + '--');
31 |
32 | if (this.postambleCRLF) {
33 | add('\r\n');
34 | }
35 |
36 | const size = body.map((part) => {
37 | if (typeof part === 'string') {
38 | return part.length
39 | } else {
40 | return part.byteLength;
41 | }
42 | }).reduce((a, b) => a + b, 0);
43 |
44 | let uint8array = new Uint8Array(size);
45 | let i = 0;
46 | body.forEach((part) => {
47 | if (typeof part === 'string') {
48 | for (let j = 0; j < part.length; i++, j++) {
49 | uint8array[i] = part.charCodeAt(j) & 0xff;
50 | }
51 | } else {
52 | for (let j = 0; j < part.byteLength; i++, j++) {
53 | uint8array[i] = part[j];
54 | }
55 | }
56 | });
57 | return uint8array.buffer;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/soap.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Vinay Pulim
3 | * MIT Licensed
4 | */
5 |
6 | import * as wsdl from './wsdl';
7 | import { security } from './security/security';
8 | import { Client } from './client';
9 | export { Client } from './client';
10 | export { security } from './security/security';
11 |
12 | export { passwordDigest } from './utils'
13 | export const WSDL = wsdl.WSDL;
14 |
15 | const cache = {}; // TODO some caching?
16 |
17 | const getFromCache = async (url, options) => {
18 | // console.log('Getting from cache', url);
19 | // console.log('Cache', cache)
20 | if (cache[url]) {
21 | // console.log('Found in cache', url);
22 | return cache[url];
23 | } else {
24 | return wsdl.open_wsdl(url, options).then(wsdl => {
25 | cache[url] = wsdl;
26 | return wsdl;
27 | })
28 | }
29 | };
30 |
31 | async function _requestWSDL(url, options) {
32 | if (options.disableCache === true) {
33 | return wsdl.open_wsdl(url, options);
34 | } else {
35 | return getFromCache(url, options);
36 | }
37 | }
38 |
39 | export async function createClient(url, options, endpoint): Promise {
40 | if (typeof options === 'undefined') {
41 | options = {};
42 | }
43 | // console.log("createClient", options)
44 | endpoint = options.endpoint || endpoint;
45 |
46 | const wsdl = await _requestWSDL(url, options);
47 | const client = new Client(wsdl, endpoint, options);
48 | return client;
49 | }
50 |
51 | export const BasicAuthSecurity = security.BasicAuthSecurity;
52 | export const NTLMSecurity = security.NTLMSecurity;
53 | export const WSSecurity = security.WSSecurity;
54 | // export const WSSecurityCert = security.WSSecurityCert;
55 | export const BearerSecurity = security.BearerSecurity;
56 | // export const ClientSSLSecurity = security.ClientSSLSecurity;
57 | // export const ClientSSLSecurityPFX = security.ClientSSLSecurityPFX;
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ngx-soap
2 |
3 | Simple SOAP client for Angular 6/10 based on amazing [node-soap](https://github.com/vpulim/node-soap).
4 |
5 | Project has been recreated from scratch with Angualr 6 CLI.
6 |
7 | ## npm
8 |
9 | 1. install ngx-soap and dependencies
10 |
11 | `npm install --save ngx-soap`
12 |
13 | `npm install --save buffer concat-stream core-js crypto-js events lodash sax stream uuid`
14 |
15 | 2. Add NgxSoapModule to your app module
16 |
17 | ```
18 | import { NgxSoapModule } from 'ngx-soap';
19 | ...
20 | @NgModule({
21 | imports: [ ..., NgxSoapModule, ... ]
22 | ...
23 | ```
24 |
25 | 3. Inject NgxSoapService in your component:
26 |
27 | ```
28 | ...
29 | import { NgxSoapService, Client, ISoapMethodResponse } from 'ngx-soap';
30 | ...
31 |
32 | @Component({
33 | selector: 'app-root',
34 | templateUrl: './app.component.html',
35 | styleUrls: ['./app.component.css']
36 | })
37 | export class AppComponent {
38 | client: Client;
39 | intA = 2;
40 | intB = 3;
41 |
42 | constructor(private soap: NgxSoapService) {
43 | this.soap.createClient('assets/calculator.wsdl').subscribe(client => this.client = client);
44 | }
45 |
46 | sum() {
47 | const body = {
48 | intA: this.intA,
49 | intB: this.intB
50 | };
51 | (this.client).Add(body).subscribe((res: ISoapMethodResponse) => this.message = res.result.AddResult);
52 | }
53 | }
54 | ```
55 |
56 |
57 | ## Local development
58 |
59 | 1. `git clone -b angular6-cli-ilb https://github.com/lula/ngx-soap.git`
60 | 2. `cd ngx-soap && npm install`
61 | 3. `ng build ngx-soap`
62 | 4. `ng test ngx-soap`
63 | 5. `ng serve --proxy-config proxy.conf.json`
64 |
65 | See example app under `src/app`
66 |
67 | ## Contributors
68 | [Andrei Bespamiatnov](https://github.com/AndreyBespamyatnov)
69 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ## 0.5.0-beta.7
4 |
5 | Client events have been removed due to problems with Angular prod bundle. See issue [#29](https://github.com/lula/ngx-soap/issues/29).
6 |
7 | If you have used in your project you should remain on beta 6 release. Just remember to turn angular bundler optimization off if you want to bundle your project with --prod option. Also, in this case, please inform me so that I know events were actually used, and I'll consider to reintroduce them.
8 |
9 | ## 0.5.0-beta.6
10 |
11 | Export security classes. ([commit 4b48395](https://github.com/lula/ngx-soap/commit/4b483952c31880ad837ae92f209f06666291ff90))
12 |
13 | ## 0.5.0-beta.5
14 |
15 | Raise error in case of calling a non existing method ([commit 77cf177](https://github.com/lula/ngx-soap/commit/77cf1772c4d042872b3326b28993bcbb0a5182c4))
16 |
17 | ## 0.5.0-beta.4
18 |
19 | Use Angular HttpClient.
20 | Observables used wherever possible.
21 |
22 | this.soap.createClient('assets/calculator.wsdl').subscribe(client => this.client = client);
23 |
24 | (this.client).Add(body).subscribe((res: ISoapMethodResponse) => this.message = res.result.AddResult);
25 |
26 | this.client.call('Add', body).subscribe((res: ISoapMethodResponse) => this.message = res.result.AddResult);
27 |
28 | ## 0.3.0-beta1
29 |
30 | Project recreated with Angualr 6 CLI.
31 |
32 | ...
33 |
34 | ## 0.2.2-beta6
35 | Call operation with client method.
36 |
37 | ## 0.2.2-beta3
38 |
39 | ### Breaking Changes
40 |
41 | Web Service operations have no callback anymore. Callback has been replaced by a Promise.
42 |
43 | Before:
44 |
45 | (client as any).Add(input, (err, wsurl: string, headers: any, xml: string) => ... )
46 |
47 | After:
48 |
49 | client.operation('Add', body).then((operation: Operation) => ... )
50 | // or
51 | (client as any).Add(body).then((operation: Operation) => ... )
52 |
53 | ## 0.2.1
54 |
55 | AOT compilation fixes (issue #1)
56 |
57 | ## 0.1.4
58 |
59 | Initial version
60 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { NgxSoapService, ISoapMethod, Client, ISoapMethodResponse } from 'ngx-soap';
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css']
8 | })
9 | export class AppComponent {
10 | intA: number;
11 | intB: number;
12 | loading: boolean;
13 | showDiagnostic: boolean;
14 | message: string;
15 | xmlResponse: string;
16 | jsonResponse: string;
17 | resultLabel: string;
18 | client: Client;
19 |
20 | constructor(private soap: NgxSoapService) {
21 | this.soap.createClient('assets/calculator.wsdl')
22 | .then(client => {
23 | console.log('Client', client);
24 | this.client = client;
25 | })
26 | .catch(err => console.log('Error', err));
27 | }
28 |
29 | sum() {
30 | this.loading = true;
31 | const body = {
32 | intA: this.intA,
33 | intB: this.intB
34 | };
35 |
36 | this.client.call('Add', body).subscribe(res => {
37 | this.xmlResponse = res.responseBody;
38 | this.message = res.result.AddResult;
39 | this.loading = false;
40 | }, err => console.log(err));
41 |
42 | // OR:
43 | // (this.client).Add(body).subscribe(
44 | // (res: ISoapMethodResponse) => {
45 | // console.log('method response', res);
46 | // this.xmlResponse = res.xml;
47 | // this.message = res.result.AddResult;
48 | // this.loading = false;
49 | // },
50 | // err => console.log(err)
51 | // );
52 | }
53 |
54 | subtract() {
55 | this.loading = true;
56 | const body = {
57 | intA: this.intA,
58 | intB: this.intB
59 | };
60 | (this.client).Subtract(body).subscribe(
61 | (res: ISoapMethodResponse) => {
62 | console.log('method response', res);
63 | this.xmlResponse = res.xml;
64 | this.message = res.result.SubtractResult;
65 | this.loading = false;
66 | },
67 | err => console.log(err)
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/ClientSSLSecurity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs')
4 | , https = require('https')
5 | , _ = require('lodash');
6 |
7 | /**
8 | * activates SSL for an already existing client
9 | *
10 | * @module ClientSSLSecurity
11 | * @param {Buffer|String} key
12 | * @param {Buffer|String} cert
13 | * @param {Buffer|String|Array} [ca]
14 | * @param {Object} [defaults]
15 | * @constructor
16 | */
17 | function ClientSSLSecurity(key, cert, ca, defaults) {
18 | if (key) {
19 | if(Buffer.isBuffer(key)) {
20 | this.key = key;
21 | } else if (typeof key === 'string') {
22 | this.key = fs.readFileSync(key);
23 | } else {
24 | throw new Error('key should be a buffer or a string!');
25 | }
26 | }
27 |
28 | if (cert) {
29 | if(Buffer.isBuffer(cert)) {
30 | this.cert = cert;
31 | } else if (typeof cert === 'string') {
32 | this.cert = fs.readFileSync(cert);
33 | } else {
34 | throw new Error('cert should be a buffer or a string!');
35 | }
36 | }
37 |
38 | if (ca) {
39 | if(Buffer.isBuffer(ca) || Array.isArray(ca)) {
40 | this.ca = ca;
41 | } else if (typeof ca === 'string') {
42 | this.ca = fs.readFileSync(ca);
43 | } else {
44 | defaults = ca;
45 | this.ca = null;
46 | }
47 | }
48 |
49 | this.defaults = {};
50 | _.merge(this.defaults, defaults);
51 |
52 | this.agent = null;
53 | }
54 |
55 | ClientSSLSecurity.prototype.toXML = function(headers) {
56 | return '';
57 | };
58 |
59 | ClientSSLSecurity.prototype.addOptions = function(options) {
60 | var httpsAgent = null;
61 |
62 | options.key = this.key;
63 | options.cert = this.cert;
64 | options.ca = this.ca;
65 | _.merge(options, this.defaults);
66 |
67 | if (!!options.forever) {
68 | if (!this.agent) {
69 | options.keepAlive = true;
70 |
71 | this.agent = new https.Agent(options);
72 | }
73 |
74 | httpsAgent = this.agent;
75 | } else {
76 | httpsAgent = new https.Agent(options);
77 | }
78 |
79 | options.agent = httpsAgent;
80 | };
81 |
82 | module.exports = ClientSSLSecurity;
83 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 | SOAP Calculator app
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Operation
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Result
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | XML Response
47 |
48 |
49 | {{ xmlResponse }}
50 |
51 |
52 |
53 |
54 | JSON Response
55 |
56 |
57 | {{ jsonResponse | json }}
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngx-soap",
3 | "version": "0.7.0",
4 | "description": "SOAP service for Angular4",
5 | "main": "src/index.js",
6 | "module": "src/index.js",
7 | "jsnext:main": "src/index.js",
8 | "typings": "src/index.d.ts",
9 | "moduleName": "ngx-soap",
10 | "scripts": {
11 | "transpile": "ngc",
12 | "bundle": "rimraf dist && npm run transpile && rollup -c rollup.config.umd.js",
13 | "postbundle": "node tools/bundle-scripts/remove-code.js",
14 | "build": "npm run bundle && npm run copy",
15 | "copy": "node tools/bundle-scripts/copy-files.js && node tools/bundle-scripts/cleanup.js",
16 | "test": "rimraf spec/out && tsc -p tsconfig.spec.json && jasmine",
17 | "build:lib": "ng build --prod ngx-soap && cp README.md dist/ngx-soap && cp LICENSE dist/ngx-soap"
18 | },
19 | "keywords": [
20 | "Angular",
21 | "Angular2",
22 | "Angular4",
23 | "Angular5",
24 | "Angular6",
25 | "Angular7",
26 | "@angular",
27 | "SOAP",
28 | "WSDL"
29 | ],
30 | "author": "Luca Lulani",
31 | "license": "MIT",
32 | "readme": "README.md",
33 | "homepage": "https://github.com/lula/ngx-soap",
34 | "bugs": {
35 | "url": "https://github.com/lula/ngx-soap/issues"
36 | },
37 | "repository": {
38 | "type": "git",
39 | "url": "https://github.com/lula/ngx-soap.git"
40 | },
41 | "dependencies": {
42 | "@angular/animations": "^10.1.2",
43 | "@angular/cdk": "^10.2.2",
44 | "@angular/common": "^10.1.2",
45 | "@angular/compiler": "^10.1.2",
46 | "@angular/core": "^10.1.2",
47 | "@angular/flex-layout": "^10.0.0-beta.32",
48 | "@angular/forms": "^10.1.2",
49 | "@angular/material": "^10.2.2",
50 | "@angular/platform-browser": "^10.1.2",
51 | "@angular/platform-browser-dynamic": "^10.1.2",
52 | "@angular/router": "^10.1.2",
53 | "buffer": "^5.1.0",
54 | "concat-stream": "^1.6.2",
55 | "core-js": "^2.5.4",
56 | "crypto-js": "^3.1.9-1",
57 | "events": "^3.0.0",
58 | "httpntlm": "^1.7.6",
59 | "lodash": "^4.17.10",
60 | "rxjs": "^6.6.3",
61 | "sax": "^1.2.4",
62 | "stream": "0.0.2",
63 | "tslib": "^2.0.0",
64 | "uuid": "^3.3.2",
65 | "xml-crypto": "^1.5.3",
66 | "zone.js": "~0.10.2"
67 | },
68 | "devDependencies": {
69 | "@angular-devkit/build-angular": "~0.1001.2",
70 | "@angular-devkit/build-ng-packagr": "~0.1001.2",
71 | "@angular/cli": "~10.1.2",
72 | "@angular/compiler-cli": "^10.1.2",
73 | "@angular/language-service": "^10.1.2",
74 | "@types/jasmine": "~2.8.6",
75 | "@types/jasminewd2": "~2.0.3",
76 | "@types/node": "^12.11.1",
77 | "codelyzer": "^5.1.2",
78 | "jasmine-core": "~3.5.0",
79 | "jasmine-spec-reporter": "~5.0.0",
80 | "karma": "~5.0.0",
81 | "karma-chrome-launcher": "~3.1.0",
82 | "karma-coverage-istanbul-reporter": "~3.0.2",
83 | "karma-jasmine": "~4.0.0",
84 | "karma-jasmine-html-reporter": "^1.5.0",
85 | "ng-packagr": "^10.1.0",
86 | "protractor": "~7.0.0",
87 | "ts-node": "~5.0.1",
88 | "tslint": "~6.1.0",
89 | "typescript": "~4.0.3"
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-shadowed-variable": true,
69 | "no-string-literal": false,
70 | "no-string-throw": true,
71 | "no-switch-case-fall-through": true,
72 | "no-trailing-whitespace": true,
73 | "no-unnecessary-initializer": true,
74 | "no-unused-expression": true,
75 | "no-var-keyword": true,
76 | "object-literal-sort-keys": false,
77 | "one-line": [
78 | true,
79 | "check-open-brace",
80 | "check-catch",
81 | "check-else",
82 | "check-whitespace"
83 | ],
84 | "prefer-const": true,
85 | "quotemark": [
86 | true,
87 | "single"
88 | ],
89 | "radix": true,
90 | "semicolon": [
91 | true,
92 | "always"
93 | ],
94 | "triple-equals": [
95 | true,
96 | "allow-null-check"
97 | ],
98 | "typedef-whitespace": [
99 | true,
100 | {
101 | "call-signature": "nospace",
102 | "index-signature": "nospace",
103 | "parameter": "nospace",
104 | "property-declaration": "nospace",
105 | "variable-declaration": "nospace"
106 | }
107 | ],
108 | "unified-signatures": true,
109 | "variable-name": false,
110 | "whitespace": [
111 | true,
112 | "check-branch",
113 | "check-decl",
114 | "check-operator",
115 | "check-separator",
116 | "check-type"
117 | ],
118 | "no-output-on-prefix": true,
119 | "no-inputs-metadata-property": true,
120 | "no-outputs-metadata-property": true,
121 | "no-host-metadata-property": true,
122 | "no-input-rename": true,
123 | "no-output-rename": true,
124 | "use-lifecycle-interface": true,
125 | "use-pipe-transform-interface": true,
126 | "component-class-suffix": true,
127 | "directive-class-suffix": true
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/weak-map';
35 | // import 'core-js/es6/set';
36 |
37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
38 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
39 |
40 | /** IE10 and IE11 requires the following for the Reflect API. */
41 | // import 'core-js/es6/reflect';
42 |
43 |
44 | /** Evergreen browsers require these. **/
45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
46 | import 'core-js/es7/reflect';
47 |
48 |
49 | /**
50 | * Web Animations `@angular/platform-browser/animations`
51 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
52 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
53 | **/
54 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
55 |
56 | /**
57 | * By default, zone.js will patch all possible macroTask and DomEvents
58 | * user can disable parts of macroTask/DomEvents patch by setting following flags
59 | */
60 |
61 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
62 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
63 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
64 |
65 | /*
66 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
67 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
68 | */
69 | // (window as any).__Zone_enable_cross_context_check = true;
70 |
71 | /***************************************************************************************************
72 | * Zone JS is required by default for Angular itself.
73 | */
74 | import 'zone.js/dist/zone'; // Included with Angular CLI.
75 |
76 |
77 |
78 | /***************************************************************************************************
79 | * APPLICATION IMPORTS
80 | */
81 |
82 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/WSSecurity.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // var crypto = require('crypto');
4 | import sha1 from 'crypto-js/sha1';
5 | import Base64 from 'crypto-js/enc-base64';
6 |
7 | // var passwordDigest = require('../utils').passwordDigest;
8 | import { passwordDigest } from '../utils';
9 |
10 | var validPasswordTypes = ['PasswordDigest', 'PasswordText'];
11 |
12 | export function WSSecurity(username, password, options) {
13 | options = options || {};
14 | this._username = username;
15 | this._password = password;
16 | //must account for backward compatibility for passwordType String param as well as object options defaults: passwordType = 'PasswordText', hasTimeStamp = true
17 | if (typeof options === 'string') {
18 | this._passwordType = options ? options : 'PasswordText';
19 | options = {};
20 | } else {
21 | this._passwordType = options.passwordType ? options.passwordType : 'PasswordText';
22 | }
23 |
24 | if (validPasswordTypes.indexOf(this._passwordType) === -1) {
25 | this._passwordType = 'PasswordText';
26 | }
27 |
28 | this._hasTimeStamp = options.hasTimeStamp || typeof options.hasTimeStamp === 'boolean' ? !!options.hasTimeStamp : true;
29 | /*jshint eqnull:true */
30 | if (options.hasNonce != null) {
31 | this._hasNonce = !!options.hasNonce;
32 | }
33 | this._hasTokenCreated = options.hasTokenCreated || typeof options.hasTokenCreated === 'boolean' ? !!options.hasTokenCreated : true;
34 | if (options.actor != null) {
35 | this._actor = options.actor;
36 | }
37 | if (options.mustUnderstand != null) {
38 | this._mustUnderstand = !!options.mustUnderstand;
39 | }
40 | }
41 |
42 | WSSecurity.prototype.toXML = function() {
43 | // avoid dependency on date formatting libraries
44 | function getDate(d) {
45 | function pad(n) {
46 | return n < 10 ? '0' + n : n;
47 | }
48 | return d.getUTCFullYear() + '-'
49 | + pad(d.getUTCMonth() + 1) + '-'
50 | + pad(d.getUTCDate()) + 'T'
51 | + pad(d.getUTCHours()) + ':'
52 | + pad(d.getUTCMinutes()) + ':'
53 | + pad(d.getUTCSeconds()) + 'Z';
54 | }
55 | var now = new Date();
56 | var created = getDate(now);
57 | var timeStampXml = '';
58 | if (this._hasTimeStamp) {
59 | var expires = getDate( new Date(now.getTime() + (1000 * 600)) );
60 | timeStampXml = "" +
61 | ""+created+"" +
62 | ""+expires+"" +
63 | "";
64 | }
65 |
66 | var password, nonce;
67 | if (this._hasNonce || this._passwordType !== 'PasswordText') {
68 | // nonce = base64 ( sha1 ( created + random ) )
69 | // var nHash = crypto.createHash('sha1');
70 | // nHash.update(created + Math.random());
71 | // nonce = nHash.digest('base64');
72 | nonce = Base64.stringify(sha1(created + Math.random(), ''));
73 | }
74 | if (this._passwordType === 'PasswordText') {
75 | password = "" + this._password + "";
76 | if (nonce) {
77 | password += "" + nonce + "";
78 | }
79 | } else {
80 | password = "" + passwordDigest(nonce, created, this._password) + "" +
81 | "" + nonce + "";
82 | }
83 |
84 | return "" +
87 | timeStampXml +
88 | "" +
89 | "" + this._username + "" +
90 | password +
91 | (this._hasTokenCreated ? "" + created + "" : "") +
92 | "" +
93 | "";
94 | };
95 |
96 | // module.exports = WSSecurity;
97 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/security/WSSecurityCert.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // var fs = require('fs');
4 | // var path = require('path');
5 | // var ejs = require('ejs');
6 | // var SignedXml = require('xml-crypto').SignedXml;
7 | // var uuid4 = require('uuid/v4');
8 |
9 | import { SignedXml } from 'xml-crypto';
10 | import uuid4 from 'uuid/v4';
11 |
12 | let wsseSecurityHeaderTemplate;
13 | let wsseSecurityTokenTemplate;
14 |
15 | function addMinutes(date, minutes) {
16 | return new Date(date.getTime() + minutes * 60000);
17 | }
18 |
19 | function dateStringForSOAP(date) {
20 | return date.getUTCFullYear() + '-' + ('0' + (date.getUTCMonth() + 1)).slice(-2) + '-' +
21 | ('0' + date.getUTCDate()).slice(-2) + 'T' + ('0' + date.getUTCHours()).slice(-2) + ":" +
22 | ('0' + date.getUTCMinutes()).slice(-2) + ":" + ('0' + date.getUTCSeconds()).slice(-2) + "Z";
23 | }
24 |
25 | function generateCreated() {
26 | return dateStringForSOAP(new Date());
27 | }
28 |
29 | function generateExpires() {
30 | return dateStringForSOAP(addMinutes(new Date(), 10));
31 | }
32 |
33 | function insertStr(src, dst, pos) {
34 | return [dst.slice(0, pos), src, dst.slice(pos)].join('');
35 | }
36 |
37 | function generateId() {
38 | return uuid4().replace(/-/gm, '');
39 | }
40 |
41 | export function WSSecurityCert(privatePEM, publicP12PEM, password) {
42 | this.publicP12PEM = publicP12PEM.toString().replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace(/(\r\n|\n|\r)/gm, '');
43 |
44 | this.signer = new SignedXml();
45 | this.signer.signingKey = {
46 | key: privatePEM,
47 | passphrase: password
48 | };
49 | this.x509Id = "x509-" + generateId();
50 |
51 | var _this = this;
52 | this.signer.keyInfoProvider = {};
53 | this.signer.keyInfoProvider.getKeyInfo = function (key) {
54 | if (!wsseSecurityTokenTemplate) {
55 | // wsseSecurityTokenTemplate = ejs.compile(fs.readFileSync(path.join(__dirname, 'templates', 'wsse-security-token.ejs')).toString());
56 | }
57 |
58 | // return wsseSecurityTokenTemplate({ x509Id: _this.x509Id });
59 | return `
60 |
61 |
62 |
63 | `;
64 | };
65 | }
66 |
67 | WSSecurityCert.prototype.postProcess = function (xml, envelopeKey) {
68 | this.created = generateCreated();
69 | this.expires = generateExpires();
70 |
71 | if (!wsseSecurityHeaderTemplate) {
72 | // wsseSecurityHeaderTemplate = ejs.compile(fs.readFileSync(path.join(__dirname, 'templates', 'wsse-security-header.ejs')).toString());
73 | }
74 |
75 | // var secHeader = wsseSecurityHeaderTemplate({
76 | // binaryToken: this.publicP12PEM,
77 | // created: this.created,
78 | // expires: this.expires,
79 | // id: this.x509Id
80 | // });
81 |
82 | var secHeader = `
83 |
86 | ${this.publicP12PEM}
90 |
91 | ${this.created}
92 | ${this.expires}
93 |
94 |
95 | `;
96 |
97 | var xmlWithSec = insertStr(secHeader, xml, xml.indexOf(''));
98 |
99 | var references = ["http://www.w3.org/2000/09/xmldsig#enveloped-signature",
100 | "http://www.w3.org/2001/10/xml-exc-c14n#"];
101 |
102 | this.signer.addReference("//*[name(.)='" + envelopeKey + ":Body']", references);
103 | this.signer.addReference("//*[name(.)='wsse:Security']/*[local-name(.)='Timestamp']", references);
104 |
105 | this.signer.computeSignature(xmlWithSec);
106 |
107 | return insertStr(this.signer.getSignatureXml(), xmlWithSec, xmlWithSec.indexOf(''));
108 | };
109 |
110 | // module.exports = WSSecurityCert;
111 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/http.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Vinay Pulim
3 | * MIT Licensed
4 | */
5 |
6 | import * as url from 'url';
7 | const req = null; // require('request');
8 | import * as httpNtlm from 'httpntlm';
9 | import { Buffer } from 'buffer';
10 |
11 | const VERSION = '0.0.0'; //require('../package.json').version;
12 |
13 | /**
14 | * A class representing the http client
15 | * @param [options] Options object. It allows the customization of
16 | * `request` module
17 | *
18 | */
19 | export function HttpClient(options) {
20 | options = options || {};
21 | this._request = options.request || req;
22 | }
23 |
24 | /**
25 | * Build the HTTP request (method, uri, headers, ...)
26 | * @param rurl The resource url
27 | * @param data The payload
28 | * @param exheaders Extra http headers
29 | * @param exoptions Extra options
30 | * @returns The http request object for the `request` module
31 | */
32 | HttpClient.prototype.buildRequest = function(rurl, data, exheaders, exoptions) {
33 | const curl = url.parse(rurl);
34 | const secure = curl.protocol === 'https:';
35 | const host = curl.hostname;
36 | const port = parseInt(curl.port, 10);
37 | const path = [curl.pathname || '/', curl.search || '', curl.hash || ''].join('');
38 | const method = data ? 'POST' : 'GET';
39 | const headers = {
40 | 'User-Agent': 'node-soap/' + VERSION,
41 | 'Accept': 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8',
42 | 'Accept-Encoding': 'none',
43 | 'Accept-Charset': 'utf-8',
44 | 'Connection': exoptions && exoptions.forever ? 'keep-alive' : 'close',
45 | 'Host': host + (isNaN(port) ? '' : ':' + port)
46 | };
47 | const attr = null;
48 | const header = null;
49 | const mergeOptions = ['headers'];
50 |
51 | if (typeof data === 'string') {
52 | headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
53 | headers['Content-Type'] = 'application/x-www-form-urlencoded';
54 | }
55 |
56 | exheaders = exheaders || {};
57 | for (const attr in exheaders) {
58 | headers[attr] = exheaders[attr];
59 | }
60 |
61 | const options: any = {
62 | uri: curl,
63 | method: method,
64 | headers: headers,
65 | followAllRedirects: true
66 | };
67 |
68 |
69 | options.body = data;
70 |
71 |
72 | exoptions = exoptions || {};
73 | for (const attr in exoptions) {
74 | if (mergeOptions.indexOf(attr) !== -1) {
75 | for (const header in exoptions[attr]) {
76 | options[attr][header] = exoptions[attr][header];
77 | }
78 | } else {
79 | options[attr] = exoptions[attr];
80 | }
81 | }
82 | console.log('Http request: %j', options);
83 | return options;
84 | };
85 |
86 | /**
87 | * Handle the http response
88 | * @param The req object
89 | * @param res The res object
90 | * @param body The http body
91 | * @param The parsed body
92 | */
93 | HttpClient.prototype.handleResponse = function(req, res, body) {
94 | console.log('Http response body: %j', body);
95 | if (typeof body === 'string') {
96 | // Remove any extra characters that appear before or after the SOAP
97 | // envelope.
98 | const match =
99 | body.replace(//, "").match(/(?:<\?[^?]*\?>[\s]*)?<([^:]*):Envelope([\S\s]*)<\/\1:Envelope>/i);
100 | if (match) {
101 | body = match[0];
102 | }
103 | }
104 | return body;
105 | };
106 |
107 | HttpClient.prototype.request = function(rurl, data, callback, exheaders, exoptions) {
108 | const self = this;
109 | const options = self.buildRequest(rurl, data, exheaders, exoptions);
110 | let req = null;
111 |
112 | if (exoptions !== undefined && exoptions.hasOwnProperty('ntlm')) {
113 | // // sadly when using ntlm nothing to return
114 | // // Not sure if this can be handled in a cleaner way rather than an if/else,
115 | // // will to tidy up if I get chance later, patches welcome - insanityinside
116 | options.url = rurl;
117 | httpNtlm[options.method.toLowerCase()](options, function (err, res) {
118 | if (err) {
119 | return callback(err);
120 | }
121 | // if result is stream
122 | if( typeof res.body !== 'string') {
123 | res.body = res.body.toString();
124 | }
125 | res.body = self.handleResponse(req, res, res.body);
126 | callback(null, res, res.body);
127 | });
128 | } else {
129 | req = self._request(options, function (err, res, body) {
130 | if (err) {
131 | return callback(err);
132 | }
133 | body = self.handleResponse(req, res, body);
134 | callback(null, res, body);
135 | });
136 | }
137 |
138 | return req;
139 | };
140 |
141 | HttpClient.prototype.requestStream = function(rurl, data, exheaders, exoptions) {
142 | const self = this;
143 | const options = self.buildRequest(rurl, data, exheaders, exoptions);
144 | return self._request(options);
145 | };
146 |
147 | // module.exports = HttpClient;
148 |
149 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "ngx-soap-app": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {},
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "aot": true,
17 | "outputPath": "dist/ngx-soap-app",
18 | "index": "src/index.html",
19 | "main": "src/main.ts",
20 | "polyfills": "src/polyfills.ts",
21 | "tsConfig": "src/tsconfig.app.json",
22 | "assets": [
23 | "src/favicon.ico",
24 | "src/assets"
25 | ],
26 | "styles": [
27 | {
28 | "input": "node_modules/@angular/material/prebuilt-themes/indigo-pink.css"
29 | },
30 | "src/styles.css"
31 | ],
32 | "scripts": []
33 | },
34 | "configurations": {
35 | "production": {
36 | "budgets": [
37 | {
38 | "type": "anyComponentStyle",
39 | "maximumWarning": "6kb"
40 | }
41 | ],
42 | "fileReplacements": [
43 | {
44 | "replace": "src/environments/environment.ts",
45 | "with": "src/environments/environment.prod.ts"
46 | }
47 | ],
48 | "optimization": true,
49 | "outputHashing": "all",
50 | "sourceMap": false,
51 | "extractCss": true,
52 | "namedChunks": false,
53 | "aot": true,
54 | "extractLicenses": true,
55 | "vendorChunk": false,
56 | "buildOptimizer": true
57 | }
58 | }
59 | },
60 | "serve": {
61 | "builder": "@angular-devkit/build-angular:dev-server",
62 | "options": {
63 | "browserTarget": "ngx-soap-app:build"
64 | },
65 | "configurations": {
66 | "production": {
67 | "browserTarget": "ngx-soap-app:build:production"
68 | }
69 | }
70 | },
71 | "extract-i18n": {
72 | "builder": "@angular-devkit/build-angular:extract-i18n",
73 | "options": {
74 | "browserTarget": "ngx-soap-app:build"
75 | }
76 | },
77 | "test": {
78 | "builder": "@angular-devkit/build-angular:karma",
79 | "options": {
80 | "main": "src/test.ts",
81 | "polyfills": "src/polyfills.ts",
82 | "tsConfig": "src/tsconfig.spec.json",
83 | "karmaConfig": "src/karma.conf.js",
84 | "styles": [
85 | {
86 | "input": "node_modules/@angular/material/prebuilt-themes/indigo-pink.css"
87 | },
88 | "styles.css"
89 | ],
90 | "scripts": [],
91 | "assets": [
92 | "src/favicon.ico",
93 | "src/assets"
94 | ]
95 | }
96 | },
97 | "lint": {
98 | "builder": "@angular-devkit/build-angular:tslint",
99 | "options": {
100 | "tsConfig": [
101 | "src/tsconfig.app.json",
102 | "src/tsconfig.spec.json"
103 | ],
104 | "exclude": [
105 | "**/node_modules/**"
106 | ]
107 | }
108 | }
109 | }
110 | },
111 | "ngx-soap-app-e2e": {
112 | "root": "e2e/",
113 | "projectType": "application",
114 | "architect": {
115 | "e2e": {
116 | "builder": "@angular-devkit/build-angular:protractor",
117 | "options": {
118 | "protractorConfig": "e2e/protractor.conf.js",
119 | "devServerTarget": "ngx-soap-app:serve"
120 | }
121 | },
122 | "lint": {
123 | "builder": "@angular-devkit/build-angular:tslint",
124 | "options": {
125 | "tsConfig": "e2e/tsconfig.e2e.json",
126 | "exclude": [
127 | "**/node_modules/**"
128 | ]
129 | }
130 | }
131 | }
132 | },
133 | "ngx-soap": {
134 | "root": "projects/ngx-soap",
135 | "sourceRoot": "projects/ngx-soap/src",
136 | "projectType": "library",
137 | "prefix": "lib",
138 | "architect": {
139 | "build": {
140 | "builder": "@angular-devkit/build-ng-packagr:build",
141 | "options": {
142 | "tsConfig": "projects/ngx-soap/tsconfig.lib.json",
143 | "project": "projects/ngx-soap/ng-package.json"
144 | },
145 | "configurations": {
146 | "production": {
147 | "project": "projects/ngx-soap/ng-package.prod.json",
148 | "tsConfig": "projects/ngx-soap/tsconfig.lib.prod.json"
149 | }
150 | }
151 | },
152 | "test": {
153 | "builder": "@angular-devkit/build-angular:karma",
154 | "options": {
155 | "main": "projects/ngx-soap/src/test.ts",
156 | "tsConfig": "projects/ngx-soap/tsconfig.spec.json",
157 | "karmaConfig": "projects/ngx-soap/karma.conf.js"
158 | }
159 | },
160 | "lint": {
161 | "builder": "@angular-devkit/build-angular:tslint",
162 | "options": {
163 | "tsConfig": [
164 | "projects/ngx-soap/tsconfig.lib.json",
165 | "projects/ngx-soap/tsconfig.spec.json"
166 | ],
167 | "exclude": [
168 | "**/node_modules/**"
169 | ]
170 | }
171 | }
172 | }
173 | }
174 | },
175 | "defaultProject": "ngx-soap-app",
176 | "cli": {
177 | "analytics": "88b524fc-7fbb-409d-94a4-e2bece002fd1"
178 | }
179 | }
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/interfaces.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from 'events';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | export interface IXmlAttribute {
6 | name: string;
7 | value: string;
8 | }
9 |
10 | export interface IWsdlBaseOptions {
11 | attributesKey?: string;
12 | valueKey?: string;
13 | xmlKey?: string;
14 | overrideRootElement?: { namespace: string; xmlnsAttributes?: IXmlAttribute[]; };
15 | ignoredNamespaces?: boolean | string[] | { namespaces?: string[]; override?: boolean; };
16 | ignoreBaseNameSpaces?: boolean;
17 | escapeXML?: boolean;
18 | returnFault?: boolean;
19 | handleNilAsNull?: boolean;
20 | wsdl_headers?: { [key: string]: any };
21 | wsdl_options?: { [key: string]: any };
22 | }
23 |
24 | export interface Definitions {
25 | descriptions: object;
26 | ignoredNamespaces: string[];
27 | messages: WsdlMessages;
28 | portTypes: WsdlPortTypes;
29 | bindings: WsdlBindings;
30 | services: WsdlServices;
31 | schemas: WsdlSchemas;
32 | valueKey: string;
33 | xmlKey: string;
34 | xmlns: WsdlXmlns;
35 | '$targetNamespace': string;
36 | '$name': string;
37 | }
38 |
39 |
40 | export interface WsdlSchemas {
41 | [prop: string]: WsdlSchema;
42 | }
43 | export interface WsdlSchema extends XsdTypeBase {
44 | children: any[];
45 | complexTypes?: WsdlElements;
46 | elements?: WsdlElements;
47 | includes: any[];
48 | name: string;
49 | nsName: string;
50 | prefix: string;
51 | types?: WsdlElements;
52 | xmlns: WsdlXmlns;
53 | }
54 | export interface WsdlElements {
55 | [prop: string]: XsdElement;
56 | }
57 | export type XsdElement = XsdElementType | XsdComplexType;
58 |
59 | export interface WsdlXmlns {
60 | wsu?: string;
61 | wsp?: string;
62 | wsam?: string;
63 | soap?: string;
64 | tns?: string;
65 | xsd?: string;
66 | __tns__?: string;
67 | [prop: string]: string | void;
68 | }
69 |
70 | export interface XsdComplexType extends XsdTypeBase {
71 | children: XsdElement[] | void;
72 | name: string;
73 | nsName: string;
74 | prefix: string;
75 | '$name': string;
76 | [prop: string]: any;
77 | }
78 |
79 | export interface XsdElementType extends XsdTypeBase {
80 | children: XsdElement[] | void;
81 | name: string;
82 | nsName: string;
83 | prefix: string;
84 | targetNSAlias: string;
85 | targetNamespace: string;
86 | '$lookupType': string;
87 | '$lookupTypes': any[];
88 | '$name': string;
89 | '$type': string;
90 | [prop: string]: any;
91 | }
92 |
93 | export interface WsdlMessages {
94 | [prop: string]: WsdlMessage;
95 | }
96 | export interface WsdlMessage extends XsdTypeBase {
97 | element: XsdElement;
98 | parts: { [prop: string]: any };
99 | '$name': string;
100 | }
101 |
102 | export interface WsdlPortTypes {
103 | [prop: string]: WsdlPortType;
104 | }
105 | export interface WsdlPortType extends XsdTypeBase {
106 | methods: { [prop: string]: XsdElement }
107 | }
108 |
109 | export interface WsdlBindings {
110 | [prop: string]: WsdlBinding;
111 | }
112 | export interface WsdlBinding extends XsdTypeBase {
113 | methods: WsdlElements;
114 | style: string;
115 | transport: string;
116 | topElements: {[prop: string]: any};
117 | }
118 |
119 | export interface WsdlServices {
120 | [prop: string]: WsdlService;
121 | }
122 | export interface WsdlService extends XsdTypeBase {
123 | ports: {[prop: string]: any};
124 | }
125 |
126 | export interface XsdTypeBase {
127 | ignoredNamespaces: string[];
128 | valueKey: string;
129 | xmlKey: string;
130 | xmlns?: WsdlXmlns,
131 | }
132 |
133 | export interface IOptions extends IWsdlBaseOptions {
134 | disableCache?: boolean;
135 | endpoint?: string;
136 | envelopeKey?: string;
137 | httpClient?: HttpClient;
138 | // request?: (options: any, callback?: (error: any, res: any, body: any) => void) => void;
139 | stream?: boolean;
140 | // wsdl options that only work for client
141 | forceSoap12Headers?: boolean;
142 | customDeserializer?: any;
143 | [key: string]: any;
144 | }
145 |
146 | export interface WSDL {
147 | constructor(definition: any, uri: string, options?: IOptions);
148 | ignoredNamespaces: string[];
149 | ignoreBaseNameSpaces: boolean;
150 | valueKey: string;
151 | xmlKey: string;
152 | xmlnsInEnvelope: string;
153 | onReady(callback: (err:Error) => void): void;
154 | processIncludes(callback: (err:Error) => void): void;
155 | describeServices(): { [k: string]: any };
156 | toXML(): string;
157 | xmlToObject(xml: any, callback?: (err:Error, result:any) => void): any;
158 | findSchemaObject(nsURI: string, qname: string): XsdElement | null | undefined;
159 | objectToDocumentXML(name: string, params: any, nsPrefix?: string, nsURI?: string, type?: string): any;
160 | objectToRpcXML(name: string, params: any, nsPrefix?: string, nsURI?: string, isParts?: any): string;
161 | isIgnoredNameSpace(ns: string): boolean;
162 | filterOutIgnoredNameSpace(ns: string): string;
163 | objectToXML(obj: any, name: string, nsPrefix?: any, nsURI?: string, isFirst?: boolean, xmlnsAttr?: any, schemaObject?: any, nsContext?: any): string;
164 | processAttributes(child: any, nsContext: any): string;
165 | findSchemaType(name: any, nsURI: any): any;
166 | findChildSchemaObject(parameterTypeObj: any, childName: any, backtrace?: any): any;
167 | uri: string;
168 | definitions: Definitions;
169 | }
170 |
171 | export interface Client extends EventEmitter {
172 | constructor(wsdl: WSDL, endpoint?: string, options?: IOptions);
173 | addBodyAttribute(bodyAttribute: any, name?: string, namespace?: string, xmlns?: string): void;
174 | addHttpHeader(name: string, value: any): void;
175 | addSoapHeader(soapHeader: any, name?: string, namespace?: any, xmlns?: string): number;
176 | changeSoapHeader(index: number, soapHeader: any, name?: string, namespace?: string, xmlns?: string): void;
177 | clearBodyAttributes(): void;
178 | clearHttpHeaders(): void;
179 | clearSoapHeaders(): void;
180 | describe(): any;
181 | getBodyAttributes(): any[];
182 | getHttpHeaders(): { [k:string]: string };
183 | getSoapHeaders(): string[];
184 | setEndpoint(endpoint: string): void;
185 | setSOAPAction(action: string): void;
186 | setSecurity(security: ISecurity): void;
187 | wsdl: WSDL;
188 | [method: string]: ISoapMethod | WSDL | Function;
189 | call(method: string, body: any, options?: any, extraHeaders?: any): Observable;
190 | }
191 |
192 | export interface ISoapMethod {
193 | (args: any, options?: any, extraHeaders?: any): Observable;
194 | }
195 |
196 | export interface ISoapMethodResponse {
197 | err: any,
198 | header: any,
199 | responseBody: string,
200 | xml: string;
201 | result: any;
202 | }
203 |
204 | export interface ISecurity {
205 | addOptions(options: any): void;
206 | toXML(): string;
207 | }
208 |
209 | export interface BasicAuthSecurity extends ISecurity {
210 | constructor(username: string, password: string, defaults?: any);
211 | addHeaders(headers: any): void;
212 | addOptions(options: any): void;
213 | toXML(): string;
214 | }
215 |
216 | export interface BearerSecurity extends ISecurity {
217 | constructor(token: string, defaults?: any);
218 | addHeaders(headers: any): void;
219 | addOptions(options: any): void;
220 | toXML(): string;
221 | }
222 |
223 | export interface WSSecurity extends ISecurity {
224 | constructor(username: string, password: string, options?: any);
225 | addOptions(options: any): void;
226 | toXML(): string;
227 | }
228 |
229 | export interface WSSecurityCert extends ISecurity {
230 | constructor(privatePEM: any, publicP12PEM: any, password: any);
231 | addOptions(options: any): void;
232 | toXML(): string;
233 | }
234 |
235 | export interface NTLMSecurity extends ISecurity {
236 | constructor(username: string, password: string, domain: string, workstation);
237 | addHeaders(headers: any): void;
238 | addOptions(options: any): void;
239 | toXML(): string;
240 | }
241 |
--------------------------------------------------------------------------------
/src/assets/calculator.wsdl:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | Adds two integers. This is a test WebService. ©DNE Online
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/nscontext.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | export class NamespaceScope {
4 | parent: any;
5 | namespaces: any;
6 | constructor(parent: any) {
7 | if (!(this instanceof NamespaceScope)) {
8 | return new NamespaceScope(parent);
9 | }
10 | this.parent = parent;
11 | this.namespaces = {};
12 | }
13 |
14 | getNamespaceURI = function(prefix, localOnly) {
15 | switch (prefix) {
16 | case 'xml':
17 | return 'http://www.w3.org/XML/1998/namespace';
18 | case 'xmlns':
19 | return 'http://www.w3.org/2000/xmlns/';
20 | default:
21 | var nsUri = this.namespaces[prefix];
22 | /*jshint -W116 */
23 | if (nsUri != null) {
24 | return nsUri.uri;
25 | } else if (!localOnly && this.parent) {
26 | return this.parent.getNamespaceURI(prefix);
27 | } else {
28 | return null;
29 | }
30 | }
31 | }
32 |
33 | getNamespaceMapping = function(prefix) {
34 | switch (prefix) {
35 | case 'xml':
36 | return {
37 | uri: 'http://www.w3.org/XML/1998/namespace',
38 | prefix: 'xml',
39 | declared: true
40 | };
41 | case 'xmlns':
42 | return {
43 | uri: 'http://www.w3.org/2000/xmlns/',
44 | prefix: 'xmlns',
45 | declared: true
46 | };
47 | default:
48 | var mapping = this.namespaces[prefix];
49 | /*jshint -W116 */
50 | if (mapping != null) {
51 | return mapping;
52 | } else if (this.parent) {
53 | return this.parent.getNamespaceMapping(prefix);
54 | } else {
55 | return null;
56 | }
57 | }
58 | }
59 |
60 | getPrefix = function(nsUri, localOnly) {
61 | switch (nsUri) {
62 | case 'http://www.w3.org/XML/1998/namespace':
63 | return 'xml';
64 | case 'http://www.w3.org/2000/xmlns/':
65 | return 'xmlns';
66 | default:
67 | for (var p in this.namespaces) {
68 | if (this.namespaces[p].uri === nsUri) {
69 | return p;
70 | }
71 | }
72 | if (!localOnly && this.parent) {
73 | return this.parent.getPrefix(nsUri);
74 | } else {
75 | return null;
76 | }
77 | }
78 | }
79 | }
80 |
81 | export class NamespaceContext {
82 | scopes: any[];
83 | prefixCount: number;
84 |
85 | constructor() {
86 | if (!(this instanceof NamespaceContext)) {
87 | return new NamespaceContext();
88 | }
89 | this.scopes = [];
90 | this.pushContext();
91 | this.prefixCount = 0;
92 | }
93 |
94 | addNamespace = function(prefix, nsUri, localOnly) {
95 | if (this.getNamespaceURI(prefix, localOnly) === nsUri) {
96 | return false;
97 | }
98 | if (this.currentScope) {
99 | this.currentScope.namespaces[prefix] = {
100 | uri: nsUri,
101 | prefix: prefix,
102 | declared: false
103 | };
104 | return true;
105 | }
106 | return false;
107 | }
108 |
109 | pushContext = function() {
110 | var scope = new NamespaceScope(this.currentScope);
111 | this.scopes.push(scope);
112 | this.currentScope = scope;
113 | return scope;
114 | }
115 |
116 | popContext = function() {
117 | var scope = this.scopes.pop();
118 | if (scope) {
119 | this.currentScope = scope.parent;
120 | } else {
121 | this.currentScope = null;
122 | }
123 | return scope;
124 | }
125 |
126 | getNamespaceURI = function(prefix, localOnly) {
127 | return this.currentScope && this.currentScope.getNamespaceURI(prefix, localOnly);
128 | }
129 |
130 | getPrefix = function(nsUri, localOnly) {
131 | return this.currentScope && this.currentScope.getPrefix(nsUri, localOnly);
132 | }
133 |
134 | registerNamespace = function(nsUri) {
135 | var prefix = this.getPrefix(nsUri);
136 | if (prefix) {
137 | // If the namespace has already mapped to a prefix
138 | return prefix;
139 | } else {
140 | // Try to generate a unique namespace
141 | while (true) {
142 | prefix = 'ns' + (++this.prefixCount);
143 | if (!this.getNamespaceURI(prefix)) {
144 | // The prefix is not used
145 | break;
146 | }
147 | }
148 | }
149 | this.addNamespace(prefix, nsUri, true);
150 | return prefix;
151 | }
152 |
153 | declareNamespace = function(prefix, nsUri) {
154 | if (this.currentScope) {
155 | var mapping = this.currentScope.getNamespaceMapping(prefix);
156 | if (mapping && mapping.uri === nsUri && mapping.declared) {
157 | return false;
158 | }
159 | this.currentScope.namespaces[prefix] = {
160 | uri: nsUri,
161 | prefix: prefix,
162 | declared: true
163 | };
164 | return true;
165 | }
166 | return false;
167 | }
168 | }
169 |
170 | /**
171 | * Scope for XML namespaces
172 | * @param [parent] Parent scope
173 | *
174 | */
175 | // export function NamespaceScope(parent) {
176 | // if (!(this instanceof NamespaceScope)) {
177 | // return NamespaceScope(parent);
178 | // }
179 | // this.parent = parent;
180 | // this.namespaces = {};
181 | // }
182 |
183 | // /**
184 | // * Namespace context that manages hierarchical scopes
185 | // * {NamespaceContext}
186 | // */
187 | // export function NamespaceContext() {
188 | // if (!(this instanceof NamespaceContext)) {
189 | // return NamespaceContext();
190 | // }
191 | // this.scopes = [];
192 | // this.pushContext();
193 | // this.prefixCount = 0;
194 | // }
195 |
196 | // /**
197 | // * Look up the namespace URI by prefix
198 | // * @param prefix Namespace prefix
199 | // * @param [localOnly] Search current scope only
200 | // * Namespace URI
201 | // */
202 | // NamespaceScope.prototype.getNamespaceURI = function(prefix, localOnly) {
203 | // switch (prefix) {
204 | // case 'xml':
205 | // return 'http://www.w3.org/XML/1998/namespace';
206 | // case 'xmlns':
207 | // return 'http://www.w3.org/2000/xmlns/';
208 | // default:
209 | // var nsUri = this.namespaces[prefix];
210 | // /*jshint -W116 */
211 | // if (nsUri != null) {
212 | // return nsUri.uri;
213 | // } else if (!localOnly && this.parent) {
214 | // return this.parent.getNamespaceURI(prefix);
215 | // } else {
216 | // return null;
217 | // }
218 | // }
219 | // };
220 |
221 | // NamespaceScope.prototype.getNamespaceMapping = function(prefix) {
222 | // switch (prefix) {
223 | // case 'xml':
224 | // return {
225 | // uri: 'http://www.w3.org/XML/1998/namespace',
226 | // prefix: 'xml',
227 | // declared: true
228 | // };
229 | // case 'xmlns':
230 | // return {
231 | // uri: 'http://www.w3.org/2000/xmlns/',
232 | // prefix: 'xmlns',
233 | // declared: true
234 | // };
235 | // default:
236 | // var mapping = this.namespaces[prefix];
237 | // /*jshint -W116 */
238 | // if (mapping != null) {
239 | // return mapping;
240 | // } else if (this.parent) {
241 | // return this.parent.getNamespaceMapping(prefix);
242 | // } else {
243 | // return null;
244 | // }
245 | // }
246 | // };
247 |
248 | // /**
249 | // * Look up the namespace prefix by URI
250 | // * @param nsUri Namespace URI
251 | // * @param [localOnly] Search current scope only
252 | // * Namespace prefix
253 | // */
254 | // NamespaceScope.prototype.getPrefix = function(nsUri, localOnly) {
255 | // switch (nsUri) {
256 | // case 'http://www.w3.org/XML/1998/namespace':
257 | // return 'xml';
258 | // case 'http://www.w3.org/2000/xmlns/':
259 | // return 'xmlns';
260 | // default:
261 | // for (var p in this.namespaces) {
262 | // if (this.namespaces[p].uri === nsUri) {
263 | // return p;
264 | // }
265 | // }
266 | // if (!localOnly && this.parent) {
267 | // return this.parent.getPrefix(nsUri);
268 | // } else {
269 | // return null;
270 | // }
271 | // }
272 | // };
273 |
274 | // /**
275 | // * Add a prefix/URI namespace mapping
276 | // * @param prefix Namespace prefix
277 | // * @param nsUri Namespace URI
278 | // * @param [localOnly] Search current scope only
279 | // * {boolean} true if the mapping is added or false if the mapping
280 | // * already exists
281 | // */
282 | // NamespaceContext.prototype.addNamespace = function(prefix, nsUri, localOnly) {
283 | // if (this.getNamespaceURI(prefix, localOnly) === nsUri) {
284 | // return false;
285 | // }
286 | // if (this.currentScope) {
287 | // this.currentScope.namespaces[prefix] = {
288 | // uri: nsUri,
289 | // prefix: prefix,
290 | // declared: false
291 | // };
292 | // return true;
293 | // }
294 | // return false;
295 | // };
296 |
297 | // /**
298 | // * Push a scope into the context
299 | // * The current scope
300 | // */
301 | // NamespaceContext.prototype.pushContext = function() {
302 | // var scope = NamespaceScope(this.currentScope);
303 | // this.scopes.push(scope);
304 | // this.currentScope = scope;
305 | // return scope;
306 | // };
307 |
308 | // /**
309 | // * Pop a scope out of the context
310 | // * The removed scope
311 | // */
312 | // NamespaceContext.prototype.popContext = function() {
313 | // var scope = this.scopes.pop();
314 | // if (scope) {
315 | // this.currentScope = scope.parent;
316 | // } else {
317 | // this.currentScope = null;
318 | // }
319 | // return scope;
320 | // };
321 |
322 | // /**
323 | // * Look up the namespace URI by prefix
324 | // * @param prefix Namespace prefix
325 | // * @param [localOnly] Search current scope only
326 | // * Namespace URI
327 | // */
328 | // NamespaceContext.prototype.getNamespaceURI = function(prefix, localOnly) {
329 | // return this.currentScope && this.currentScope.getNamespaceURI(prefix, localOnly);
330 | // };
331 |
332 | // /**
333 | // * Look up the namespace prefix by URI
334 | // * @param nsURI Namespace URI
335 | // * @param [localOnly] Search current scope only
336 | // * Namespace prefix
337 | // */
338 | // NamespaceContext.prototype.getPrefix = function(nsUri, localOnly) {
339 | // return this.currentScope && this.currentScope.getPrefix(nsUri, localOnly);
340 | // };
341 |
342 | // /**
343 | // * Register a namespace
344 | // * @param nsUri Namespace URI
345 | // * The matching or generated namespace prefix
346 | // */
347 | // NamespaceContext.prototype.registerNamespace = function(nsUri) {
348 | // var prefix = this.getPrefix(nsUri);
349 | // if (prefix) {
350 | // // If the namespace has already mapped to a prefix
351 | // return prefix;
352 | // } else {
353 | // // Try to generate a unique namespace
354 | // while (true) {
355 | // prefix = 'ns' + (++this.prefixCount);
356 | // if (!this.getNamespaceURI(prefix)) {
357 | // // The prefix is not used
358 | // break;
359 | // }
360 | // }
361 | // }
362 | // this.addNamespace(prefix, nsUri, true);
363 | // return prefix;
364 | // };
365 |
366 | // /**
367 | // * Declare a namespace prefix/uri mapping
368 | // * @param prefix Namespace prefix
369 | // * @param nsUri Namespace URI
370 | // * true if the declaration is created
371 | // */
372 | // NamespaceContext.prototype.declareNamespace = function(prefix, nsUri) {
373 | // if (this.currentScope) {
374 | // var mapping = this.currentScope.getNamespaceMapping(prefix);
375 | // if (mapping && mapping.uri === nsUri && mapping.declared) {
376 | // return false;
377 | // }
378 | // this.currentScope.namespaces[prefix] = {
379 | // uri: nsUri,
380 | // prefix: prefix,
381 | // declared: true
382 | // };
383 | // return true;
384 | // }
385 | // return false;
386 | // };
387 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/_soap.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { EventEmitter } from 'events';
4 | import * as BluebirdPromise from 'bluebird';
5 |
6 | export interface ISoapMethod {
7 | (args: any, callback: (err: any, result: any, raw: any, soapHeader: any) => void, options?: any, extraHeaders?: any): void;
8 | }
9 |
10 | export interface ISoapServiceMethod {
11 | (args:any, callback?: (data: any) => void, headers?: any, req?: any): any;
12 | }
13 |
14 | // SOAP Fault 1.1 & 1.2
15 | export type ISoapFault = ISoapFault12 | ISoapFault11;
16 |
17 | // SOAP Fault 1.1
18 | export interface ISoapFault11 {
19 | Fault: {
20 | faultcode: number | string;
21 | faultstring: string;
22 | detail?: string;
23 | statusCode?: number;
24 | };
25 | }
26 |
27 | // SOAP Fault 1.2
28 | // 1.2 also supports additional, optional elements:
29 | // Role, Node, Detail. Should be added when soap module implements them
30 | // https://www.w3.org/TR/soap12/#soapfault
31 | export interface ISoapFault12 {
32 | Fault: {
33 | Code: { Value: string; Subcode?: { Value: string; }; };
34 | Reason: { Text: string; };
35 | statusCode?: number;
36 | };
37 | }
38 |
39 | export interface ISecurity {
40 | addOptions(options: any): void;
41 | toXML(): string;
42 | }
43 |
44 | export interface IServicePort {
45 | [methodName: string]: ISoapServiceMethod;
46 | }
47 |
48 | export interface IService {
49 | [portName: string]: IServicePort;
50 | }
51 |
52 | export interface IServices {
53 | [serviceName: string]: IService;
54 | }
55 |
56 | export interface IXmlAttribute {
57 | name: string;
58 | value: string;
59 | }
60 |
61 | export interface IWsdlBaseOptions {
62 | attributesKey?: string;
63 | valueKey?: string;
64 | xmlKey?: string;
65 | overrideRootElement?: { namespace: string; xmlnsAttributes?: IXmlAttribute[]; };
66 | ignoredNamespaces?: boolean | string[] | { namespaces?: string[]; override?: boolean; };
67 | ignoreBaseNameSpaces?: boolean;
68 | escapeXML?: boolean;
69 | returnFault?: boolean;
70 | handleNilAsNull?: boolean;
71 | wsdl_headers?: { [key: string]: any };
72 | wsdl_options?: { [key: string]: any };
73 | }
74 |
75 | export interface IOptions extends IWsdlBaseOptions {
76 | disableCache?: boolean;
77 | endpoint?: string;
78 | envelopeKey?: string;
79 | httpClient?: HttpClient;
80 | request?: (options: any, callback?: (error: any, res: any, body: any) => void) => void;
81 | stream?: boolean;
82 | // wsdl options that only work for client
83 | forceSoap12Headers?: boolean;
84 | customDeserializer?: any;
85 | [key: string]: any;
86 | }
87 |
88 | export interface IOneWayOptions {
89 | responseCode?: number;
90 | emptyBody?: boolean;
91 | }
92 |
93 | export interface IServerOptions extends IWsdlBaseOptions {
94 | path: string;
95 | services: IServices;
96 | xml?: string;
97 | uri?: string;
98 | suppressStack?: boolean;
99 | oneWay?: IOneWayOptions;
100 | [key: string]: any;
101 | }
102 |
103 | export interface Definitions {
104 | descriptions: object;
105 | ignoredNamespaces: string[];
106 | messages: WsdlMessages;
107 | portTypes: WsdlPortTypes;
108 | bindings: WsdlBindings;
109 | services: WsdlServices;
110 | schemas: WsdlSchemas;
111 | valueKey: string;
112 | xmlKey: string;
113 | xmlns: WsdlXmlns;
114 | '$targetNamespace': string;
115 | '$name': string;
116 | }
117 |
118 | export interface XsdTypeBase {
119 | ignoredNamespaces: string[];
120 | valueKey: string;
121 | xmlKey: string;
122 | xmlns?: WsdlXmlns,
123 | }
124 |
125 |
126 | export interface WsdlSchemas {
127 | [prop: string]: WsdlSchema;
128 | }
129 | export interface WsdlSchema extends XsdTypeBase {
130 | children: any[];
131 | complexTypes?: WsdlElements;
132 | elements?: WsdlElements;
133 | includes: any[];
134 | name: string;
135 | nsName: string;
136 | prefix: string;
137 | types?: WsdlElements;
138 | xmlns: WsdlXmlns;
139 | }
140 | export interface WsdlElements {
141 | [prop: string]: XsdElement;
142 | }
143 | export type XsdElement = XsdElementType | XsdComplexType;
144 |
145 | export interface WsdlXmlns {
146 | wsu?: string;
147 | wsp?: string;
148 | wsam?: string;
149 | soap?: string;
150 | tns?: string;
151 | xsd?: string;
152 | __tns__?: string;
153 | [prop: string]: string | void;
154 | }
155 |
156 | export interface XsdComplexType extends XsdTypeBase {
157 | children: XsdElement[] | void;
158 | name: string;
159 | nsName: string;
160 | prefix: string;
161 | '$name': string;
162 | [prop: string]: any;
163 | }
164 |
165 | export interface XsdElementType extends XsdTypeBase {
166 | children: XsdElement[] | void;
167 | name: string;
168 | nsName: string;
169 | prefix: string;
170 | targetNSAlias: string;
171 | targetNamespace: string;
172 | '$lookupType': string;
173 | '$lookupTypes': any[];
174 | '$name': string;
175 | '$type': string;
176 | [prop: string]: any;
177 | }
178 |
179 | export interface WsdlMessages {
180 | [prop: string]: WsdlMessage;
181 | }
182 | export interface WsdlMessage extends XsdTypeBase {
183 | element: XsdElement;
184 | parts: { [prop: string]: any };
185 | '$name': string;
186 | }
187 |
188 | export interface WsdlPortTypes {
189 | [prop: string]: WsdlPortType;
190 | }
191 | export interface WsdlPortType extends XsdTypeBase {
192 | methods: { [prop: string]: XsdElement }
193 | }
194 |
195 | export interface WsdlBindings {
196 | [prop: string]: WsdlBinding;
197 | }
198 | export interface WsdlBinding extends XsdTypeBase {
199 | methods: WsdlElements;
200 | style: string;
201 | transport: string;
202 | topElements: {[prop: string]: any};
203 | }
204 |
205 | export interface WsdlServices {
206 | [prop: string]: WsdlService;
207 | }
208 | export interface WsdlService extends XsdTypeBase {
209 | ports: {[prop: string]: any};
210 | }
211 |
212 | export class WSDL {
213 | constructor(definition: any, uri: string, options?: IOptions);
214 | ignoredNamespaces: string[];
215 | ignoreBaseNameSpaces: boolean;
216 | valueKey: string;
217 | xmlKey: string;
218 | xmlnsInEnvelope: string;
219 | onReady(callback: (err:Error) => void): void;
220 | processIncludes(callback: (err:Error) => void): void;
221 | describeServices(): { [k: string]: any };
222 | toXML(): string;
223 | xmlToObject(xml: any, callback?: (err:Error, result:any) => void): any;
224 | findSchemaObject(nsURI: string, qname: string): XsdElement | null | undefined;
225 | objectToDocumentXML(name: string, params: any, nsPrefix?: string, nsURI?: string, type?: string): any;
226 | objectToRpcXML(name: string, params: any, nsPrefix?: string, nsURI?: string, isParts?: any): string;
227 | isIgnoredNameSpace(ns: string): boolean;
228 | filterOutIgnoredNameSpace(ns: string): string;
229 | objectToXML(obj: any, name: string, nsPrefix?: any, nsURI?: string, isFirst?: boolean, xmlnsAttr?: any, schemaObject?: any, nsContext?: any): string;
230 | processAttributes(child: any, nsContext: any): string;
231 | findSchemaType(name: any, nsURI: any): any;
232 | findChildSchemaObject(parameterTypeObj: any, childName: any, backtrace?: any): any;
233 | uri: string;
234 | definitions: Definitions;
235 | }
236 |
237 | export class Client extends EventEmitter {
238 | constructor(wsdl: WSDL, endpoint?: string, options?: IOptions);
239 | addBodyAttribute(bodyAttribute: any, name?: string, namespace?: string, xmlns?: string): void;
240 | addHttpHeader(name: string, value: any): void;
241 | addSoapHeader(soapHeader: any, name?: string, namespace?: any, xmlns?: string): number;
242 | changeSoapHeader(index: number, soapHeader: any, name?: string, namespace?: string, xmlns?: string): void;
243 | clearBodyAttributes(): void;
244 | clearHttpHeaders(): void;
245 | clearSoapHeaders(): void;
246 | describe(): any;
247 | getBodyAttributes(): any[];
248 | getHttpHeaders(): { [k:string]: string };
249 | getSoapHeaders(): string[];
250 | setEndpoint(endpoint: string): void;
251 | setSOAPAction(action: string): void;
252 | setSecurity(security: ISecurity): void;
253 | wsdl: WSDL;
254 | [method: string]: ISoapMethod | WSDL | Function;
255 | }
256 |
257 | export function createClient(url: string, callback: (err: any, client: Client) => void): void;
258 | export function createClient(url: string, options: IOptions, callback: (err: any, client: Client) => void): void;
259 | export function createClientAsync(url: string, options?: IOptions, endpoint?: string): BluebirdPromise;
260 |
261 | export class Server extends EventEmitter {
262 | constructor(server: any, path: string, services: IServices, wsdl: WSDL, options: IServerOptions);
263 | path: string;
264 | services: IServices;
265 | wsdl: WSDL;
266 | addSoapHeader(soapHeader: any, name?: string, namespace?: any, xmlns?: string): number;
267 | changeSoapHeader(index: any, soapHeader: any, name?: any, namespace?: any, xmlns?: any): void;
268 | getSoapHeaders(): string[];
269 | clearSoapHeaders(): void;
270 | log(type: string, data: any): any;
271 | authorizeConnection(req: any): boolean;
272 | authenticate(security: ISecurity): boolean;
273 | }
274 |
275 | export function listen(server: any, path: string, service: any, wsdl: string): Server;
276 | export function listen(server: any, options: IServerOptions): Server;
277 |
278 | export class HttpClient {
279 | constructor(options?: IOptions);
280 | buildRequest(rurl: string, data: any | string, exheaders?: { [key: string]: any }, exoptions?: { [key: string]: any }): any;
281 | handleResponse(req: any, res: any, body: any | string): any | string;
282 | request(rurl: string, data: any | string, callback: (err: any, res: any, body: any | string) => void, exheaders?: { [key: string]: any }, exoptions?: { [key: string]: any }): any;
283 | requestStream(rurl: string, data: any | string, exheaders?: { [key: string]: any }, exoptions?: { [key: string]: any }): any;
284 | }
285 |
286 | export class BasicAuthSecurity implements ISecurity {
287 | constructor(username: string, password: string, defaults?: any);
288 | addHeaders(headers: any): void;
289 | addOptions(options: any): void;
290 | toXML(): string;
291 | }
292 |
293 | export class BearerSecurity implements ISecurity {
294 | constructor(token: string, defaults?: any);
295 | addHeaders(headers: any): void;
296 | addOptions(options: any): void;
297 | toXML(): string;
298 | }
299 |
300 | export class WSSecurity implements ISecurity {
301 | constructor(username: string, password: string, options?: any);
302 | addOptions(options: any): void;
303 | toXML(): string;
304 | }
305 |
306 | export class WSSecurityCert implements ISecurity {
307 | constructor(privatePEM: any, publicP12PEM: any, password: any);
308 | addOptions(options: any): void;
309 | toXML(): string;
310 | }
311 |
312 | export class ClientSSLSecurity implements ISecurity {
313 | constructor(key: string | Buffer, cert: string | Buffer, ca?: string | any[] | Buffer, defaults?: any);
314 | constructor(key: string | Buffer, cert: string | Buffer, defaults?: any);
315 | addOptions(options: any): void;
316 | toXML(): string;
317 | }
318 |
319 | export class ClientSSLSecurityPFX implements ISecurity {
320 | constructor(pfx: string | Buffer, passphrase: string, defaults?: any);
321 | constructor(pfx: string | Buffer, defaults?: any);
322 | addOptions(options: any): void;
323 | toXML(): string;
324 | }
325 |
326 | export function passwordDigest(nonce: string, created: string, password: string): string;
327 |
328 | // Below are added for backwards compatibility for previous @types/soap users.
329 | export interface Security extends ISecurity {}
330 | export interface SoapMethod extends ISoapMethod {}
331 | export interface Option extends IOptions {}
332 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/ngx-soap.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { HttpClientModule, HttpRequest } from '@angular/common/http';
3 | import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
4 |
5 | import { ISoapMethodResponse } from 'ngx-soap/ngx-soap';
6 | import { NgxSoapService } from './ngx-soap.service';
7 | import { NgxSoapModule } from './ngx-soap.module';
8 |
9 |
10 | const PROXIED_CALCULATOR_WSDL = `
11 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | Adds two integers. This is a test WebService. ©DNE Online
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | `;
217 |
218 | let service: NgxSoapService;
219 | let httpMock: HttpTestingController;
220 |
221 | describe('NgxSoapService', () => {
222 | beforeEach(() => {
223 | TestBed.configureTestingModule({
224 | imports: [HttpClientModule, HttpClientTestingModule, NgxSoapModule],
225 | providers: [NgxSoapService]
226 | });
227 | service = TestBed.inject(NgxSoapService);
228 | httpMock = TestBed.inject(HttpTestingController);
229 | });
230 |
231 | afterEach(() => {
232 | httpMock.verify();
233 | });
234 |
235 | it('should be created', () => {
236 | expect(service).toBeTruthy();
237 | });
238 |
239 | it('should create client from calculator.wsdl', () => {
240 | service.createClient('/calculator.wsdl', { disableCache: true })
241 | .then(client => {
242 | expect(client).toBeTruthy();
243 | client.call('Add', { intA: 3, intB: 2 }, { exchangeId: '11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000' })
244 | })
245 | .catch(err => console.log('Error', err));
246 |
247 | const req = httpMock.expectOne('/calculator.wsdl');
248 | expect(req.request.method).toBe("GET");
249 | req.flush(PROXIED_CALCULATOR_WSDL);
250 | });
251 |
252 | it('should create client from calculator.wsdl', () => {
253 | service.createClient('/calculator.wsdl', { disableCache: true })
254 | .then(client => expect(client).toBeTruthy())
255 | .catch(err => console.log('Error', err));
256 |
257 | let req = httpMock.expectOne('/calculator.wsdl');
258 | req.flush(PROXIED_CALCULATOR_WSDL);
259 | httpMock.verify();
260 | });
261 |
262 | it('3 + 2 should be equal to 5', () => {
263 | service.createClient('/calculator.wsdl', { disableCache: true })
264 | .then(client => {
265 | client.call('Add', {
266 | intA: 3,
267 | intB: 2
268 | }, { exchangeId: '11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000' }).subscribe((soapResponse: ISoapMethodResponse) => {
269 | expect(soapResponse.result.AddResult).toBe(5);
270 | }, err => console.error(err));
271 |
272 | let req = httpMock.expectOne('/calculator/calculator.asmx');
273 | let res = {
274 | headers: {},
275 | body: ``
276 | };
277 | req.flush('5');
278 | httpMock.verify();
279 | })
280 | .catch(err => console.log('Error', err));
281 |
282 | let req = httpMock.expectOne('/calculator.wsdl');
283 | expect(req.request.method).toBe("GET");
284 | req.flush(PROXIED_CALCULATOR_WSDL);
285 | });
286 |
287 | it('should raise an error when calling a missing operation', () => {
288 | service
289 | .createClient('/calculator.wsdl', { disableCache: true })
290 | .then(client => {
291 | const method = 'NonExistingMethod';
292 | client
293 | .call(method, {}, { exchangeId: '11bf5b37-e0b8-42e0-8dcf-dc8c4aefc000' })
294 | .subscribe(() => { }, err => expect(err).toBe(`Method ${method} not found`));
295 | });
296 |
297 | const req = httpMock.expectOne('/calculator.wsdl');
298 | expect(req.request.method).toBe("GET");
299 | req.flush(PROXIED_CALCULATOR_WSDL);
300 | });
301 | });
302 |
--------------------------------------------------------------------------------
/projects/ngx-soap/src/lib/soap/client.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Vinay Pulim
3 | * MIT Licensed
4 | */
5 |
6 | import { HttpClient, HttpResponse } from '@angular/common/http';
7 | import * as assert from 'assert';
8 | import { findPrefix } from './utils';
9 | import * as _ from 'lodash';
10 | import uuid4 from 'uuid/v4';
11 | import { from, Observable, throwError } from 'rxjs';
12 | import { flatMap, map } from 'rxjs/operators';
13 | import { Multipart } from './multipart';
14 | import { SoapAttachment } from './soapAttachment';
15 |
16 | const nonIdentifierChars = /[^a-z$_0-9]/i;
17 |
18 | export const Client = function(wsdl, endpoint, options) {
19 | options = options || {};
20 | this.wsdl = wsdl;
21 | this._initializeOptions(options);
22 | this._initializeServices(endpoint);
23 | this.httpClient = options.httpClient as HttpClient;
24 | const promiseOptions: any = { multiArgs: true };
25 | if (options.overridePromiseSuffix) {
26 | promiseOptions.suffix = options.overridePromiseSuffix;
27 | }
28 | Promise.all([this, promiseOptions]);
29 | };
30 |
31 | Client.prototype.addSoapHeader = function(soapHeader, name, namespace, xmlns) {
32 | if (!this.soapHeaders) {
33 | this.soapHeaders = [];
34 | }
35 | if (typeof soapHeader === 'object') {
36 | soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true);
37 | }
38 | return this.soapHeaders.push(soapHeader) - 1;
39 | };
40 |
41 | Client.prototype.changeSoapHeader = function(index, soapHeader, name, namespace, xmlns) {
42 | if (!this.soapHeaders) {
43 | this.soapHeaders = [];
44 | }
45 | if (typeof soapHeader === 'object') {
46 | soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true);
47 | }
48 | this.soapHeaders[index] = soapHeader;
49 | };
50 |
51 | Client.prototype.getSoapHeaders = function() {
52 | return this.soapHeaders;
53 | };
54 |
55 | Client.prototype.clearSoapHeaders = function() {
56 | this.soapHeaders = null;
57 | };
58 |
59 | Client.prototype.addHttpHeader = function(name, value) {
60 | if (!this.httpHeaders) {
61 | this.httpHeaders = {};
62 | }
63 | this.httpHeaders[name] = value;
64 | };
65 |
66 | Client.prototype.getHttpHeaders = function() {
67 | return this.httpHeaders;
68 | };
69 |
70 | Client.prototype.clearHttpHeaders = function() {
71 | this.httpHeaders = {};
72 | };
73 |
74 | Client.prototype.addBodyAttribute = function(bodyAttribute, name, namespace, xmlns) {
75 | if (!this.bodyAttributes) {
76 | this.bodyAttributes = [];
77 | }
78 | if (typeof bodyAttribute === 'object') {
79 | let composition = '';
80 | Object.getOwnPropertyNames(bodyAttribute).forEach(function(prop, idx, array) {
81 | composition += ' ' + prop + '="' + bodyAttribute[prop] + '"';
82 | });
83 | bodyAttribute = composition;
84 | }
85 | if (bodyAttribute.substr(0, 1) !== ' ') bodyAttribute = ' ' + bodyAttribute;
86 | this.bodyAttributes.push(bodyAttribute);
87 | };
88 |
89 | Client.prototype.getBodyAttributes = function() {
90 | return this.bodyAttributes;
91 | };
92 |
93 | Client.prototype.clearBodyAttributes = function() {
94 | this.bodyAttributes = null;
95 | };
96 |
97 | Client.prototype.setEndpoint = function(endpoint) {
98 | this.endpoint = endpoint;
99 | this._initializeServices(endpoint);
100 | };
101 |
102 | Client.prototype.describe = function() {
103 | const types = this.wsdl.definitions.types;
104 | return this.wsdl.describeServices();
105 | };
106 |
107 | Client.prototype.setSecurity = function(security) {
108 | this.security = security;
109 | };
110 |
111 | Client.prototype.setSOAPAction = function(SOAPAction) {
112 | this.SOAPAction = SOAPAction;
113 | };
114 |
115 | Client.prototype._initializeServices = function(endpoint) {
116 | const definitions = this.wsdl.definitions,
117 | services = definitions.services;
118 | for (const name in services) {
119 | this[name] = this._defineService(services[name], endpoint);
120 | }
121 | };
122 |
123 | Client.prototype._initializeOptions = function(options) {
124 | this.streamAllowed = options.stream;
125 | this.normalizeNames = options.normalizeNames;
126 | this.wsdl.options.attributesKey = options.attributesKey || 'attributes';
127 | this.wsdl.options.envelopeKey = options.envelopeKey || 'soap';
128 | this.wsdl.options.preserveWhitespace = !!options.preserveWhitespace;
129 | if (options.ignoredNamespaces !== undefined) {
130 | if (options.ignoredNamespaces.override !== undefined) {
131 | if (options.ignoredNamespaces.override === true) {
132 | if (options.ignoredNamespaces.namespaces !== undefined) {
133 | this.wsdl.options.ignoredNamespaces = options.ignoredNamespaces.namespaces;
134 | }
135 | }
136 | }
137 | }
138 | if (options.overrideRootElement !== undefined) {
139 | this.wsdl.options.overrideRootElement = options.overrideRootElement;
140 | }
141 | this.wsdl.options.forceSoap12Headers = !!options.forceSoap12Headers;
142 | };
143 |
144 | Client.prototype._defineService = function(service, endpoint) {
145 | const ports = service.ports,
146 | def = {};
147 | for (const name in ports) {
148 | def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
149 | }
150 | return def;
151 | };
152 |
153 | Client.prototype._definePort = function(port, endpoint) {
154 | const location = endpoint,
155 | binding = port.binding,
156 | methods = binding.methods,
157 | def = {};
158 | for (const name in methods) {
159 | def[name] = this._defineMethod(methods[name], location);
160 | const methodName = this.normalizeNames ? name.replace(nonIdentifierChars, '_') : name;
161 | this[methodName] = def[name];
162 | }
163 | return def;
164 | };
165 |
166 | Client.prototype._defineMethod = function(method, location) {
167 | const self = this;
168 | let temp = null;
169 | return function(args, options, extraHeaders): Observable {
170 | return self._invoke(method, args, location, options, extraHeaders);
171 | };
172 | };
173 |
174 | Client.prototype._invoke = function(method, args, location, options, extraHeaders): Observable {
175 | let self = this,
176 | name = method.$name,
177 | input = method.input,
178 | output = method.output,
179 | style = method.style,
180 | defs = this.wsdl.definitions,
181 | envelopeKey = this.wsdl.options.envelopeKey,
182 | ns = defs.$targetNamespace,
183 | encoding = '',
184 | message = '',
185 | xml = null,
186 | req = null,
187 | soapAction = null,
188 | alias = findPrefix(defs.xmlns, ns),
189 | headers: any = {
190 | 'Content-Type': 'text/xml; charset=utf-8'
191 | },
192 | xmlnsSoap = 'xmlns:' + envelopeKey + '="http://schemas.xmlsoap.org/soap/envelope/"';
193 |
194 | if (this.wsdl.options.forceSoap12Headers) {
195 | headers['Content-Type'] = 'application/soap+xml; charset=utf-8';
196 | xmlnsSoap = 'xmlns:' + envelopeKey + '="http://www.w3.org/2003/05/soap-envelope"';
197 | }
198 |
199 | if (this.SOAPAction) {
200 | soapAction = this.SOAPAction;
201 | } else if (method.soapAction !== undefined && method.soapAction !== null) {
202 | soapAction = method.soapAction;
203 | } else {
204 | soapAction = (ns.lastIndexOf('/') !== ns.length - 1 ? ns + '/' : ns) + name;
205 | }
206 |
207 | if (!this.wsdl.options.forceSoap12Headers) {
208 | headers.SOAPAction = '"' + soapAction + '"';
209 | }
210 |
211 | options = options || {};
212 |
213 | //Add extra headers
214 | for (const header in this.httpHeaders) {
215 | headers[header] = this.httpHeaders[header];
216 | }
217 | for (const attr in extraHeaders) {
218 | headers[attr] = extraHeaders[attr];
219 | }
220 |
221 | // Allow the security object to add headers
222 | if (self.security && self.security.addHeaders) self.security.addHeaders(headers);
223 | if (self.security && self.security.addOptions) self.security.addOptions(options);
224 |
225 | if (style === 'rpc' && (input.parts || input.name === 'element' || args === null)) {
226 | assert.ok(!style || style === 'rpc', 'invalid message definition for document style binding');
227 | message = self.wsdl.objectToRpcXML(name, args, alias, ns, input.name !== 'element');
228 | method.inputSoap === 'encoded' && (encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ');
229 | } else {
230 | assert.ok(!style || style === 'document', 'invalid message definition for rpc style binding');
231 | // pass `input.$lookupType` if `input.$type` could not be found
232 | message = self.wsdl.objectToDocumentXML(input.$name, args, input.targetNSAlias, input.targetNamespace, input.$type || input.$lookupType);
233 | }
234 | xml =
235 | '' +
236 | '<' +
237 | envelopeKey +
238 | ':Envelope ' +
239 | xmlnsSoap +
240 | ' ' +
241 | 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
242 | encoding +
243 | this.wsdl.xmlnsInEnvelope +
244 | '>' +
245 | (self.soapHeaders || self.security
246 | ? '<' +
247 | envelopeKey +
248 | ':Header>' +
249 | (self.soapHeaders ? self.soapHeaders.join('\n') : '') +
250 | (self.security && !self.security.postProcess ? self.security.toXML() : '') +
251 | '' +
252 | envelopeKey +
253 | ':Header>'
254 | : '') +
255 | '<' +
256 | envelopeKey +
257 | ':Body' +
258 | (self.bodyAttributes ? self.bodyAttributes.join(' ') : '') +
259 | (self.security && self.security.postProcess ? ' Id="_0"' : '') +
260 | '>' +
261 | message +
262 | '' +
263 | envelopeKey +
264 | ':Body>' +
265 | '' +
266 | envelopeKey +
267 | ':Envelope>';
268 |
269 | if (self.security && self.security.postProcess) {
270 | xml = self.security.postProcess(xml, envelopeKey);
271 | }
272 |
273 | if (options && options.postProcess) {
274 | xml = options.postProcess(xml);
275 | }
276 |
277 | self.lastMessage = message;
278 | self.lastRequest = xml;
279 | self.lastEndpoint = location;
280 |
281 | const tryJSONparse = function(body) {
282 | try {
283 | return JSON.parse(body);
284 | } catch (err) {
285 | return undefined;
286 | }
287 | };
288 |
289 | return from(SoapAttachment.fromFormFiles(options.attachments)).pipe(
290 | map((soapAttachments: SoapAttachment[]) => {
291 | if (!soapAttachments.length) {
292 | return xml;
293 | }
294 |
295 | if (options.forceMTOM || soapAttachments.length > 0) {
296 | const start = uuid4();
297 | const boundry = uuid4();
298 | let action = null;
299 | if (headers['Content-Type'].indexOf('action') > -1) {
300 | for (const ct of headers['Content-Type'].split('; ')) {
301 | if (ct.indexOf('action') > -1) {
302 | action = ct;
303 | }
304 | }
305 | }
306 |
307 | headers['Content-Type'] =
308 | 'multipart/related; type="application/xop+xml"; start="<' + start + '>"; start-info="text/xml"; boundary="' + boundry + '"';
309 | if (action) {
310 | headers['Content-Type'] = headers['Content-Type'] + '; ' + action;
311 | }
312 |
313 | const multipart: any[] = [
314 | {
315 | 'Content-Type': 'application/xop+xml; charset=UTF-8; type="text/xml"',
316 | 'Content-ID': '<' + start + '>',
317 | body: xml
318 | }
319 | ];
320 |
321 | soapAttachments.forEach((attachment: SoapAttachment) => {
322 | multipart.push({
323 | 'Content-Type': attachment.mimetype + ';',
324 | 'Content-Transfer-Encoding': 'binary',
325 | 'Content-ID': '<' + (attachment.contentId || attachment.name) + '>',
326 | 'Content-Disposition': 'attachment; name="' + attachment.name + '"; filename="' + attachment.name + '"',
327 | body: attachment.body
328 | });
329 | });
330 |
331 | return new Multipart().build(multipart, boundry);
332 | }
333 | }),
334 | flatMap((body: any) =>
335 | (self.httpClient)
336 | .post(location, body, {
337 | headers: headers,
338 | responseType: 'text',
339 | observe: 'response'
340 | })
341 | .pipe(
342 | map((response: HttpResponse) => {
343 | self.lastResponse = response.body;
344 | self.lastResponseHeaders = response && response.headers;
345 | return parseSync(response.body, response);
346 | })
347 | )
348 | )
349 | );
350 |
351 | function parseSync(body, response: HttpResponse) {
352 | let obj;
353 | try {
354 | obj = self.wsdl.xmlToObject(body);
355 | } catch (error) {
356 | // When the output element cannot be looked up in the wsdl and the body is JSON
357 | // instead of sending the error, we pass the body in the response.
358 | if (!output || !output.$lookupTypes) {
359 | // debug('Response element is not present. Unable to convert response xml to json.');
360 | // If the response is JSON then return it as-is.
361 | const json = _.isObject(body) ? body : tryJSONparse(body);
362 | if (json) {
363 | return { err: null, response, responseBody: json, header: undefined, xml };
364 | }
365 | }
366 | error.response = response;
367 | error.body = body;
368 | // self.emit('soapError', error, eid);
369 | throw error;
370 | }
371 | return finish(obj, body, response);
372 | }
373 |
374 | function finish(obj, responseBody, response) {
375 | let result = null;
376 |
377 | if (!output) {
378 | // one-way, no output expected
379 | return { err: null, response: null, responseBody, header: obj.Header, xml };
380 | }
381 |
382 | // If it's not HTML and Soap Body is empty
383 | if (!obj.html && !obj.Body) {
384 | return { err: null, obj, responseBody, header: obj.Header, xml };
385 | }
386 |
387 | if (typeof obj.Body !== 'object') {
388 | const error: any = new Error('Cannot parse response');
389 | error.response = response;
390 | error.body = responseBody;
391 | return { err: error, obj, responseBody, header: undefined, xml };
392 | }
393 |
394 | result = obj.Body[output.$name];
395 | // RPC/literal response body may contain elements with added suffixes I.E.
396 | // 'Response', or 'Output', or 'Out'
397 | // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5
398 | if (!result) {
399 | result = obj.Body[output.$name.replace(/(?:Out(?:put)?|Response)$/, '')];
400 | }
401 | if (!result) {
402 | ['Response', 'Out', 'Output'].forEach(function(term) {
403 | if (obj.Body.hasOwnProperty(name + term)) {
404 | return (result = obj.Body[name + term]);
405 | }
406 | });
407 | }
408 |
409 | return { err: null, result, responseBody, header: obj.Header, xml };
410 | }
411 | };
412 |
413 | Client.prototype.call = function(method: string, body: any, options?: any, extraHeaders?: any): Observable {
414 | if (!this[method]) {
415 | return throwError(`Method ${method} not found`);
416 | }
417 |
418 | return (this[method]).call(this, body, options, extraHeaders);
419 | };
420 |
--------------------------------------------------------------------------------