diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 572ca1b9..e8e8fed2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,58 +1,148 @@ -#Contribution Guidelines - -Thank you for your support! node-soap wouldn't be where it is today without contributors like you who are willing to take the time to improve it for everyone else. - -Because SOAP Web Services can differ amongst implementations, there is high risk involved in making changes. What works for your WSDL, might not work with another. It is therefore _essential_ that contributors to node-soap adhere to these guidelines. - -##Filing issues -* Please look through the issues that are currently open in the attempt to find one that matches yours. -* If you find an issue that matches yours, please submit your documentation about it there as it will help everyone understand it more. -* If you plan on fixing the issue, please take the time to fix it first and then provide a Pull Request. -* Please be descriptive in your issue titles I.E. "Error occurs when calling client.foo on WSDL without import element." - -##Submitting a Pull Request -* Pull Requests **must be rebased to the latest version of master and _squashed to a single commit_** i.e. `git checkout master;git pull upstream master;git checkout feature-branch;git rebase -i master` -* Pull Requests **must have accompanying tests** (either Unit or Request/Response Sample tests are welcome). Your chances of getting the PR merged are very low if you don't provide any tests. -* Pull Requests must have passing travis builds. -* Pull Requests must be able to merge automatically from github. -* Please **do not close a pull request due to a request to rebase**. Git is a powerful VCS and deserves your time in learning how to rebase properly. Pull Requests are updated automatically on github when you force push to your branch after rebasing. - -Very useful articles/help on this topic: - - [GitHub Help - About Git rebase](https://help.github.com/articles/about-git-rebase/) - - [GitHub Help - Using Git rebase](https://help.github.com/articles/using-git-rebase/) - -* Please use descriptive commit messages. Commit messages are used during the creation of history and release notes. You'll make the job of maintainers much easier by doing this. - -##Making Changes -* Any and all pull requests to change documentation or typos are welcome! -* Any WSDL checked in should be as small and as generic as possible. This is to keep the size of the codebase from growing too large and to keep the reason for submitting the WSDL clear I.E. if the WSDL was submitted because attributes were not being parsed on response XML, then it would be appropriate to submit a WSDL that defines a response with attributes *and nothing else*. If you find an issue with the parser not being able to handle large WSDLs, then it would be appropriate to submit a large WSDL to recreate the issue with. -* If your issue is WSDL related: -```` - 1. Make your WSDL as generic as possible to recreate the issue - 2. Add the WSDL to the appropriate path in test/wsdl. - 3. Commit your changes to a feature branch within your fork. - 4. Issue a pull request. -```` - -* If your issue is client related: -```` - 1. Capture the request / response XML via client.lastRequest and client.lastResponse as well as the WSDL. - 2. Make the WSDL, request, and response XML as generic as possible. - 3. Only include the messages or operations that are having issues. - 4. Add the appropriate files to test/request-response-samples (see the README therein) - 5. Commit your changes to a feature branch within your fork. - 6. Issue a pull request -```` - -* If your issue is neither WSDL nor client related: -```` - 1. Provide a test of some form in an appropriate *-test.js file under test/ - 2. Commit your changes to a feature branch within your fork. - 3. Issue a pull request. -```` - -##Issue Expiration -Any pull request or issue filed is subject to an expiration date. We will close any open issue that has not received a response within a 2 week timeframe. The goal is not to sweep dirt under the rug, but to keep the focus on merging in pull requests. Please provide pull requests that meet the above criteria wherever possible. - -##Other ways you can contribute -Please add response, request, and WSDL files to test/wsdl, and test/request-response-samples (see README therein). Doing so documents behavior and reduces the likelihood that bugs will be introduced by future pull requests. +### Contributing ### + +Thank you for your interest in `strong-soap`, an open source project +administered by StrongLoop. + +Contributing to `strong-soap` is easy. In a few simple steps: + + * Ensure that your effort is aligned with the project's roadmap by + talking to the maintainers, especially if you are going to spend a + lot of time on it. + + * Make something better or fix a bug. + + * Adhere to code style outlined in the [Google C++ Style Guide][] and + [Google Javascript Style Guide][]. + + * Sign the [Contributor License Agreement](https://cla.strongloop.com/agreements/strongloop/strong-soap) + + * Submit a pull request through Github. + + +### Contributor License Agreement ### + +``` + Individual Contributor License Agreement + + By signing this Individual Contributor License Agreement + ("Agreement"), and making a Contribution (as defined below) to + StrongLoop, Inc. ("StrongLoop"), You (as defined below) accept and + agree to the following terms and conditions for Your present and + future Contributions submitted to StrongLoop. Except for the license + granted in this Agreement to StrongLoop and recipients of software + distributed by StrongLoop, You reserve all right, title, and interest + in and to Your Contributions. + + 1. Definitions + + "You" or "Your" shall mean the copyright owner or the individual + authorized by the copyright owner that is entering into this + Agreement with StrongLoop. + + "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, that + is intentionally submitted by You to StrongLoop for inclusion in, + or documentation of, any of the products owned or managed by + StrongLoop ("Work"). For purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication + sent to StrongLoop or its representatives, including but not + limited to communication or electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, + or on behalf of, StrongLoop for the purpose of discussing and + improving the Work, but excluding communication that is + conspicuously marked or otherwise designated in writing by You as + "Not a Contribution." + + 2. You Grant a Copyright License to StrongLoop + + Subject to the terms and conditions of this Agreement, You hereby + grant to StrongLoop and recipients of software distributed by + StrongLoop, a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable copyright license to reproduce, prepare + derivative works of, publicly display, publicly perform, + sublicense, and distribute Your Contributions and such derivative + works under any license and without any restrictions. + + 3. You Grant a Patent License to StrongLoop + + Subject to the terms and conditions of this Agreement, You hereby + grant to StrongLoop and to recipients of software distributed by + StrongLoop a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable (except as stated in this Section) + patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work under any license and + without any restrictions. The patent license You grant to + StrongLoop under this Section applies only to those patent claims + licensable by You that are necessarily infringed by Your + Contributions(s) alone or by combination of Your Contributions(s) + with the Work to which such Contribution(s) was submitted. If any + entity institutes a patent litigation against You or any other + entity (including a cross-claim or counterclaim in a lawsuit) + alleging that Your Contribution, or the Work to which You have + contributed, constitutes direct or contributory patent + infringement, any patent licenses granted to that entity under + this Agreement for that Contribution or Work shall terminate as + of the date such litigation is filed. + + 4. You Have the Right to Grant Licenses to StrongLoop + + You represent that You are legally entitled to grant the licenses + in this Agreement. + + If Your employer(s) has rights to intellectual property that You + create, You represent that You have received permission to make + the Contributions on behalf of that employer, that Your employer + has waived such rights for Your Contributions, or that Your + employer has executed a separate Corporate Contributor License + Agreement with StrongLoop. + + 5. The Contributions Are Your Original Work + + You represent that each of Your Contributions are Your original + works of authorship (see Section 8 (Submissions on Behalf of + Others) for submission on behalf of others). You represent that to + Your knowledge, no other person claims, or has the right to claim, + any right in any intellectual property right related to Your + Contributions. + + You also represent that You are not legally obligated, whether by + entering into an agreement or otherwise, in any way that conflicts + with the terms of this Agreement. + + You represent that Your Contribution submissions include complete + details of any third-party license or other restriction (including, + but not limited to, related patents and trademarks) of which You + are personally aware and which are associated with any part of + Your Contributions. + + 6. You Don't Have an Obligation to Provide Support for Your Contributions + + You are not expected to provide support for Your Contributions, + except to the extent You desire to provide support. You may provide + support for free, for a fee, or not at all. + + 6. No Warranties or Conditions + + StrongLoop acknowledges that unless required by applicable law or + agreed to in writing, You provide Your Contributions on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER + EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES + OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR + FITNESS FOR A PARTICULAR PURPOSE. + + 7. Submission on Behalf of Others + + If You wish to submit work that is not Your original creation, You + may submit it to StrongLoop separately from any Contribution, + identifying the complete details of its source and of any license + or other restriction (including, but not limited to, related + patents, trademarks, and license agreements) of which You are + personally aware, and conspicuously marking the work as + "Submitted on Behalf of a Third-Party: [named here]". + + 8. Agree to Notify of Change of Circumstances + + You agree to notify StrongLoop of any facts or circumstances of + which You become aware that would make these representations + inaccurate in any respect. Email us at callback@strongloop.com. +``` diff --git a/History.md b/History.md deleted file mode 100644 index 9ee3b8c0..00000000 --- a/History.md +++ /dev/null @@ -1,342 +0,0 @@ -0.15.0 / 2016-05-09 -================= -* [FIX] Make `ursa` an optional dependency since it's currently nearly impossible to install `soap` on a windows machine otherwise (#832) -* [FIX] Fixed issue of referencing element in another namespace (#831) -* [FIX] Fixed incorrect WSDL in `CDATA` tests (#830) -* [FIX] Added mocks for node.js streams `cork`/`uncork` in tests (for `node >= 4.x`) (#829) -* [ENHANCEMENT] Added basic `CDATA` support (#787) -* [DOC] Added missing documentation about `Client.setEndpoint(url)` (#827) -* [ENHANCEMENT] Added `toc` node-module in order to generate TOC in README.md via `npm run toc` command (#826) -* [FIX] Fix `elementFormDefault` handling (#822) -* [FIX] Added missing `compress` node-module to `package.json` dependencies (#823) -* [ENHANCEMENT] The client `response` event is now triggered with the "raw" `IncomingMessage` object as second parameter (#816) -* [DOC] Added note about the `keep-alive` workaround to prevent truncation of longer chunked reponses in `node > 0.10.x` (#818) -* [ENHANCEMENT] Make it possible to overwrite the request module, e.g. for using `multipart-body` for file up- and downloads (#817) - -0.14.0 / 2016-04-12 -================= -* [ENHANCEMENT] Allow to call methods with `callback` as last param in order to align with node.js `callback last` pattern (#814) -* [ENHANCEMENT] Re-enabled `ignoreBaseNameSpaces` option (#809) -* [FIX] Avoid overwriting request headers with options in client method invocation (#813) -* [ENHANCEMENT] Accept `time` value in in `extraHeaders` options in order to retrieve the `lastElapsedTime` for the response (#811) -* [ENHANCEMENT] Allow to set a custom envelope key for the SOAP request (#812) -* [FIX] Removed double declaration of `WSDL` variable in `lib/soap.js` (#810) -* [DOC] Added documentation for `wsdl_options` and `wsdl_headers` options in `createClient()` method (#806) -* [ENHANCEMENT] Added support to override the namespace definition of the root element (#805) -* [ENHANCEMENT] Ignore "whitespace only" differences in `request/response sample tests` in order to make differences easier to spot (#804) -* [ENHANCEMENT] Added support for WSSecurity XML signing with x509 certificats. Dropped support for node.js < 0.10.x (#801) -* [ENHANCEMENT] Remove assertions/checkin of certificates in `ClientSSLSecurity` (#800) - -0.13.0 / 2016-02-16 -================= -* [FIX] Maintain `ignoredNamespaces` option when processing WSDL includes (#796) -* [ENHANCEMENT] SOAP Headers for server response & `changeSoapHeader()` method for client & server (#792) -* [ENHANCEMENT] Added XML declaration (version & encoding) to client requests (#797) -* [DOC] Added example for `server.options` to README, fixed typos in CONTRIBUTING (#798) -* [FIX] Keep `nsContext` stack consistent even on recursive calls (#799) -* [FIX] Prevent NPE when processing an empty children array (#789) - -0.12.0 / 2016-02-02 -================= -* [MAINTENANCE] updating lodash to 3.x.x -* [FIX] Schema overwrite when include a xsd with <xsd:include> (#788) - -0.11.4 / 2016-01-09 -================= -* [MAINTENANCE] Adding coverage to project. - -0.11.3 / 2016-01-09 -================= -* [ENHANCEMENT] Overriding the namespace prefix with empty prefix. (#779) -* [FIX] Wrong namespace on elements when complexType has same name. (#781) -* [FIX] Improved 'https' pattern matching for local files with name starting with 'http'. (#780) -* [FIX] Handles SOAP result null output. (#778) - -0.11.2 / 2016-01-08 -================= -* [FIX] Return null instead of empty object. (#733, #707, #784) -* [DOC] Adds commas and semicolons to listen(...) example. (#782) -* [MAINTENANCE] Temporarily skiping test from #768. - -0.11.1 / 2015-12-15 -================= -* [ENHANCEMENT] Adding ClientSSLSecurityPFX for use in requests (#768) -* [FIX] Remove SOAPAction http header in SOAP 1.2, extra header was causing some servers to trip. (#775) -* [FIX] When an error occur, send HTTP 500 status code. (#774) -* [FIX] Fixed issue when an error was undefined: undefined. (#771) -* [FIX] Add missing type attribute for PasswordText in WSSecurity and update related tests. (#754) - -0.11.0 / 2015-10-31 -================= -* [ENHANCEMENT] Now passing request to services in server.js. (#769) -* [ENHANCEMENT] Adding the ability to add headers in client requests. (#770) -* [MAINTENANCE] Adding gitter badge to README and disabling issues. (#731) -* [FIX] Stop sending Object prototype methods as XML. (#699) - -0.10.3 / 2015-10-23 -================= -* [ENHANCEMENT] Adding createErroringStub to soap-stub. (#765) -* [ENHANCEMENT] `forceSoap12Headers` option to add SOAP v1.2 request headers. (#755) - -0.10.2 / 2015-10-22 -================= -* [ENHANCEMENT] Adding security to soap-stub. (#764) - -0.10.1 / 2015-10-22 -================= -* [ENHANCEMENT] Adding soap-stub. (#763) - -0.10.0 / 2015-10-21 -================= -* [FIX] xml namespace/element/type handling. (#756) - -0.9.5 / 2015-10-15 -================= -* [FIX] Allow circular XSD files to be loaded. (#745) -* [ENHANCEMENT] Timestamp is now optional. (#735) -* [DOC] Formatting History.md 0.9.4 notes. - -0.9.4 / 2015-09-28 -================= -* [MAINTENANCE] Adding node v4.0 to .travis.yml. (#729) -* [MAINTENANCE] Increasing mocha test timeout to 10 seconds. (#732) -* [FIX] Resolve element references when other types are referenced. (#725) -* [DOC] Update Readme.md -* [ENHANCEMENT] New Ignorebasenamespaces option. (#716) -* [ENHANCEMENT] Add optional statusCode on soap fault. (#715) -* [FIX] Fix for wsdl retrieval using soap.createClient with special options.httpClient. Before this, the specified client was not used when fetching the wsdl file. This fix will force the wsdl to use the specified httpClient. (#714) -* [FIX] Allow WSDL to be loaded from HTTPS sites. (#694) - -0.9.3 / 2015-09-08 -================= -* [ENHANCEMENT] Allow namespace overriding for elements. (#709) -* [MAINTENANCE] Disable travis emails. - -0.9.2 / 2015-09-08 -================= -* [ENHANCEMENT] Add support for xsd element ref. (#700) -* [MAINTENANCE] Moving travis build to containers. -* [MAINTENANCE] Add request sample for an operation without any parameters. (#703) -* [DOC] update spelling and formatting to clarify several sections of Readme. (#708) -* [ENHANCEMENT] Add the correct namespace alias for operations without parameters by simply removing the special case where input.parts is empty. If special logic is wanted for this case, it should be contained in objectToRpcXML in any case. (#703) -* [FIX] Fix a typo in WSDL#findChildParameterObject. (#686) -* [FIX] Fixed SOAP Fault errors not being raised as errors. (#676) -* [FIX] Use diffrent namespace styles for soap fault 1.1 and 1.2. (#674) - -0.9.1 / 2015-05-30 -================= -* [FIX] Received empty Strings are now returned as empty String rather than an empty Object. (#637) - -* [FIX] Get current namespace when parent namespace is an empty String. Fixes #533. (#661) - -* [DOC] Update README.md with documentation for #660 introduced customization of `httpClient` and `request` libs in `client.options`. (#664) - -* [FIX] Take configured "ignored namespaces" into account when processing `objectToXml()`. Fixes #537. (#662) - -* [LIC] Update license attribute to follow the new [npm conventions](https://docs.npmjs.com/files/package.json#license). (#663) - -* [ENHANCEMENT] Add ability to customize `http` client / `request` lib on client creation. (#660) - -* [FIX] Support `xsi:type` Schema on Element. Fixes #606. (#639) - -* [FIX] Make parsing of recursive Elements in `wsdl` work. (#658) - -0.9.0 / 2015-05-18 -================= -* [FIX] Fix to allow request options and headers to persist for all includes. Fix to properly handle when an import/include starts with a schema element. (#608) - -* [FIX] Do not end request for keep-alive connections (#600) - -* [ENHANCEMENT] Added Client 'response' event (#610) - -* [FIX] If response is json, then error should not be thrown. Fix issue #580 (#581) - -* [FIX] Sub-namespace should be correct regardless of order of enumeration i.e. should not be overriden by other prop's namespace (#607) - -* [DOC] Added a section about Server Events to README.md (#596) - -* [ENHANCEMENT] Added Server 'request' event (#595) - -* [ENHANCEMENT] Add support for One-Way Operations (#590) - -* [FIX] `lib/wsdl.js` util function `extend()` doesn't throw an Error when handling elements that are not objects. (#589) - -* [ENHANCEMENT] ClientSSLSecurity now accepts a `ca`-certificate. (#588) - -* [ENHANCEMENT] ClientSSLSecurity should be able to take a Buffer as `key` and `cert` parameter. Additionally the certificates are checked whether they are correct or not (starting with `-----BEGIN`). (#586) - -* [ENHANCEMENT] Add support for sending NULL values (#578) - -* [ENHANCEMENT] Follow 302 redirects, don't mix quotes (#577) - -* [DOC] Update CONTRIBUTING.md - -* [FIX] Respond with security timestamp if request had one (#579) - - -0.8.0 / 2015-02-17 -================= -* [ENHANCEMENT] `node-soap` is now also compatible (and tested) with `node v0.12.0` and `io.js` too. (#571) - -* [FIX] Adds support for attributes in the `SOAP Body` Element (fixes #386). (#574) - -0.7.0 / 2015-02-10 -================= -* [ENHANCEMENT] Server emits a `headers` event to globally handle SOAP Headers. (#564 ) - -* [ENHANCEMENT] A service method can send back a SOAP Fault response to a client by throwing an object that contains a `Fault` property. (#563) - -* [FIX] Don't throw an Error if an `element` is not defined. (#562) - -* [ENHANCEMENT] Added more primitive types (`['positiveInteger', 'nonPositiveInteger', 'negativeInteger', 'nonNegativeInteger']`). (#560) - -* [FIX] Respect empty SOAP actions in operations. (#554) - -* [ENHANCEMENT] The client now emits `message`, `request` and `soapError` events. (#547, #559) - -* [ENHANCEMENT] The server is now aware of the SOAP header(s) from incoming request. (#551) - -* [ENHANCEMENT] Until now, only the SOAP Body was returned from the invoked client method. With this PR also the SOAP Header(s) will be returned. (#539) - -0.6.1 / 2014-12-20 -================== -* [ENHANCEMENT] Allow logging of received `XML` prior to parsing and processing it, which allows better debugging of incoming`XML`. (#524) - -* [ENHANCEMENT] Add support for importing external `wsdl`. (#523) - -* [FIX] Use correct namespaces for elements which consist of an array. (#522) - -* [FIX] Use correct namespaces for elements which have a different base namespace. (#521) - -* [FIX] Don't throw an `Error` when `typeElement` is undefined in `ExtensionElement#description` method. (#515) - -* [FIX] Only supply `nonce` when a password digest is used to avoid `schema` validation errors. (#496) - -* [FIX] Allow `wsdl:documentation` element under `wsdl:message`. (#508) - -* [FIX] Use correct namespaces in sequences with imported elements. (#502) - -* [FIX] Ignore default `tns` and disabled default `tns` specification in first element of the body. (#506) - -* [ENHANCEMENT] Define `$xml` to pass plain `XML` object. (#485) -The `$xml` key is used to pass an `XML` Object to the request without adding a namespace or parsing the string. - -* [FIX] Updated '#extend' method to avoid overriding properties and ensure the 'inheritance' of `<xsd:extension base=...>` usage. (#493) - -0.6.0 / 2014-10-29 -================= -* [ENHANCEMENT] Adding bearer security type Exporting security type for usage. -* [ENHANCEMENT] The qualified elementFormQualified must be respected only when the current element is not a global element. The namespace attribute is only needed if it's not included in the xmlns. -* [FIX] Remove automatic port appending to "Host" header. -* [FIX] Avoid creating soap:Header container when there are no children. -* [FIX] Allowing a 'null' argument for WSDL methods that take no arguments. -* [FIX] Wrong initialization of xmlns array when handling rpc stype wsdl. -* [FIX] Fault handling. err should be used less frequently now. -* [FIX] Added checking if there is input and output for operations under bindings section. -* [FIX] XSD conflict with same namespace. - -0.5.1 / 2014-07-11 -================= -* [ENHANCEMENT] Add "defaults" parameter to BasicAuthSecurity's constructor -* [ENHANCEMENT] Added possibility to set a custom `valueKey` for the parsed values from XML SOAP Response -* [FIX] don't append port 80 to Host if not needed -* [FIX] Remove possible existing BOM characters from XML String before passing it to `WSDL#_fromXML()` and parsing it. -* [FIX] Handling nil attributes in response xml - -0.5.0 / 2014-07-11 -================= -* [ENHANCEMENT] Allowing namespace prefixes to be ignored via config. -* [ENHANCEMENT] wsdl should handle more types -* [FIX] Handle defined messages ending with "Response", "Out", or "Output" -* [FIX] Adding default attributesKey to server and allowing the property to be configurable fixing issue #406 -* [FIX] Remove extra characters before and after soap envelope -* [FIX] Allow operations to not have definitions -* [FIX] Ignore unknown elements -* [FIX] Keep ns from top-level -* [FIX] Check status code of invocation response - -0.4.7 / 2014-06-16 -================= -* [ENHANCEMENT] Allow request elements to have both content and attributes. - -0.4.6 / 2014-06-16 -================= -* Fix for the `elementFormDefault` functionality. -* Fix determining the namespace for complex elements. -* Add support for the `elementFormDefault` schema attribute. -* Fixing duplicate code which had gotten introduced because of a merge. -* Added the ability to specify elements in a $value attribute for complex types. -* Allowing the property name "attributes" to be configurable. -* Fix for andling object arrays. -* Fix for WSDL and Schema interaction. -* Allowing response.xml to be optional in tests. -* Allowing request.xml and response.json to be optional for tests. -* Fix for adding an undefined XML namespace. -* Added some documentation on options object when calling createClient. -* Fix for namespaces in headers not being added appropriately. - -0.4.5 / 2014-05-13 -================= -* Fixed: Unspecified binding style defaults to 'document' (#346, #208) -* Fixed: WSDL parse errors bubble up (#344) -* Fixed: AssertionError: Invalid child type when WSDL contains imports (#322, #337) -* Fixed: TargetNamespace not loaded when import in schema (#327, #325) - -0.4.4 / 2014-04-16 -================= -* Added namespace prefixes to SOAP headers. #307 -* Provided more documentation around security protocols in the README. #321 -* Added lodash. #321 -* Added a deefault parameter to ClientSSLSecurity. #321 -* Fix to reset the generated namespace number. #308 -* Fixed maximum callstack errors on certain responses. #257 - -0.4.3 / 2014-04-07 -================= -* Refactored WS-security. small modifications to pull #275 -* Updated readme to add documentation for passing options to a client request -* Added null check for portType and methods[methodname].output -* Fixed issue where requests that included compex types led to invalid request XML. -* Support for attributes array elements and support for complex extensions with array elements. -* Make sure callback is done asynchronously for a cached wsdl -* Added WSDL inheritance support (#133). - -0.4.2 / 2014-03-13 -================= -* Added the ability to inspect and clear soap headers. -* Reducing test wsdl size. -* No longer prefixing elements with a default namespace prefix i.e. xmlns. - -0.4.1 / 2014-03-04 -================= -Note: an error occurred publishing this version to npm. This version was tagged, so it can be referrenced via git. - * package; increased minor version to 0.4.1 - * Adding an npmignore on test/ - * Tests are linted - * Attributes may be added to requests and parsed from responses - * Tests were added for ssl and client authentication - * Support for import elements in WSDL documents. - * Version in server response matches package.json - * Describe errors fixed on OutputElements. - * Support for Fault handling. - -0.4.0 / 2014-02-15 -================== - - * package; increased minor version to 0.4 (xml parser change, tests) - * remove execute privileges on files #216 - * add travis #219 - * add jshint for index.js #220 - * remove execute permissions on .gitignore #227 - * fixed; fix requests if SOAP service is not on port 80, do not crash on errors #228 - * fixed; undefined value for json in client method when message names end with Out or Output. #243 - * add non xmlns attributes to elements during response parsing #241 - * package; replace expat dependency with sax #246 - * fixed; "Uncaught TypeError: Cannot read property '0' of undefined" #248 - -0.3.2 / 2014-01-21 -================== - - * fixed; http request callback fires twice on error #120 - * fixed; handle connection errors #192 - * package; include mocha in devDependencies diff --git a/LICENSE b/LICENSE index f2ba6a42..602e77b5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,25 @@ -Copyright (C) 2013 Vinay Pulim +Copyright (c) IBM Corp. 2016. All Rights Reserved. +Node module: strong-soap +This project is licensed under the MIT License, full text below. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +-------- -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +MIT license -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..921614be --- /dev/null +++ b/NOTICE @@ -0,0 +1,23 @@ +This product includes software developed at https://github.com/vpulim/node-soap +under the following MIT license. + +Copyright (C) 2013 Vinay Pulim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/PUBLISHING.md b/PUBLISHING.md deleted file mode 100644 index abf976c3..00000000 --- a/PUBLISHING.md +++ /dev/null @@ -1,28 +0,0 @@ -Publishing -=================== - -This document describes the steps a maintainer of this project generally takes in -order to publish a newer version of `node-soap`. - -## Ideals -* Pull Requests that alter, add, or correct functionality have a single commit. -* All commit messages are descriptive. -* Maintainers spend little time looking at git history to update HISTORY.md. - -## Process -1. Checkout the commit that you would like to publish. This is usually accomplished - with `git checkout master`. -2. Run `git log --oneline` -3. Copy the commit messages above the last release commit message into History.md. -4. Consolidate the commit messages: - * Remove any futile commits I.E. "Removing white space" - * Remove Pull Request merge commits. In some cases, you may need to reference the issue in - order to get the commit message for that Pull Request. - * Prefix commit messages with "Enhancement", "Fixed", "Deprecated" and so forth - accordingly. - * Reword line items as necessary. -5. Update package.json to the appropriate version for the release. -6. Commit your changes to master and push them up to github. -7. Use the github interface to create a tag. - * Use existing release notes as a reference when adding the release notes to github. -8. `npm publish`. diff --git a/Readme.md b/Readme.md index c5df72a1..da2ca23c 100644 --- a/Readme.md +++ b/Readme.md @@ -2,35 +2,22 @@ > A SOAP client and server for node.js. -This module lets you connect to web services using SOAP. It also provides a server that allows you to run your own SOAP services. +This module provides SOAP client for invoking Web Services. It also provides a mock up SOAP server capability to create and test your Web service. This module is re-implemented based on `node-soap` module. <!-- Run `npm run toc` to update below section --> <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> -- [Features:](#features) +- [Features](#features) - [Install](#install) -- [Where can I file an issue?](#where-can-i-file-an-issue) -- [Module](#module) - - [soap.createClient(url[, options], callback) - create a new SOAP client from a WSDL url. Also supports a local filesystem path.](#soapcreateclienturl-options-callback---create-a-new-soap-client-from-a-wsdl-url-also-supports-a-local-filesystem-path) - - [soap.listen(*server*, *path*, *services*, *wsdl*) - create a new SOAP server that listens on *path* and provides *services*.](#soaplistenserver-path-services-wsdl---create-a-new-soap-server-that-listens-on-path-and-provides-services) - - [Options](#options) - - [Server Logging](#server-logging) - - [Server Events](#server-events) - - [SOAP Fault](#soap-fault) - - [Server security example using PasswordDigest](#server-security-example-using-passworddigest) - - [Server connection authorization](#server-connection-authorization) -- [SOAP Headers](#soap-headers) - - [Received SOAP Headers](#received-soap-headers) - - [Outgoing SOAP Headers](#outgoing-soap-headers) - [Client](#client) - [Client.describe() - description of services, ports and methods as a JavaScript object](#clientdescribe---description-of-services-ports-and-methods-as-a-javascript-object) - [Client.setSecurity(security) - use the specified security protocol](#clientsetsecuritysecurity---use-the-specified-security-protocol) - [Client.*method*(args, callback) - call *method* on the SOAP service.](#clientmethodargs-callback---call-method-on-the-soap-service) - [Client.*service*.*port*.*method*(args, callback[, options[, extraHeaders]]) - call a *method* using a specific *service* and *port*](#clientserviceportmethodargs-callback-options-extraheaders---call-a-method-using-a-specific-service-and-port) - - [Client.*lastRequest* - the property that contains last full soap request for client logging](#clientlastrequest---the-property-that-contains-last-full-soap-request-for-client-logging) - - [Client.setEndpoint(url) - overwrite the SOAP service endpoint address](#clientsetendpointurl---overwrite-the-soap-service-endpoint-address) + - [Client.*lastRequest*](#clientlastrequest) + - [Client.setEndpoint(url)](#clientsetendpointurl) - [Client Events](#client-events) - [Security](#security) - [BasicAuthSecurity](#basicauthsecurity) @@ -38,10 +25,23 @@ This module lets you connect to web services using SOAP. It also provides a ser - [ClientSSLSecurity](#clientsslsecurity) - [WSSecurity](#wssecurity) - [WSSecurityCert](#wssecuritycert) -- [Handling XML Attributes, Value and XML (wsdlOptions).](#handling-xml-attributes-value-and-xml-wsdloptions) - - [Specifying the exact namespace definition of the root element](#specifying-the-exact-namespace-definition-of-the-root-element) -- [Handling "ignored" namespaces](#handling-ignored-namespaces) -- [Handling "ignoreBaseNameSpaces" attribute](#handling-ignorebasenamespaces-attribute) +- [SOAP Headers](#soap-headers) + - [Received SOAP Headers](#received-soap-headers) + - [Outgoing SOAP Headers](#outgoing-soap-headers) +- [XML Attributes](#xml-attributes) + - [Handling XML Attributes](#handling-xml-attributes) + - [Overriding the value key](#overriding-the-value-key) + - [Overriding the xml key](#overriding-the-xml-key) +- [XMLHandler](#xmlhandler) +- [WSDL](#wsdl) +- [Server](#server) + - [soap.listen(*server*, *path*, *services*, *wsdl*) - create a new SOAP server that listens on *path* and provides *services*.](#soaplistenserver-path-services-wsdl---create-a-new-soap-server-that-listens-on-path-and-provides-services) + - [Options](#options) + - [Server Logging](#server-logging) + - [Server Events](#server-events) + - [SOAP Fault](#soap-fault) + - [Server security example using PasswordDigest](#server-security-example-using-passworddigest) + - [Server connection authorization](#server-connection-authorization) - [soap-stub](#soap-stub) - [Example](#example) - [Contributors](#contributors) @@ -50,9 +50,11 @@ This module lets you connect to web services using SOAP. It also provides a ser ## Features: -* Very simple API -* Handles both RPC and Document schema types -* Supports multiRef SOAP messages (thanks to [@kaven276](https://github.com/kaven276)) +* Full SOAP Client capability & mock up SOAP server capability +* Handles both RPC and Document styles +* Handles both SOAP 1.1 and SOAP 1.2 Fault +* APIs to parse XML --> JSON and JSON --> XML +* API to describe WSDL document * Support for both synchronous and asynchronous method handlers * WS-Security (currently only UsernameToken and PasswordText encoding is supported) @@ -64,277 +66,92 @@ Install with [npm](http://github.com/isaacs/npm): npm install strong-soap ``` -## Module - -### soap.createClient(url[, options], callback) - create a new SOAP client from a WSDL url. Also supports a local filesystem path. +## Client -``` javascript - var soap = require('strong-soap'); - var url = 'http://example.com/wsdl?wsdl'; - var args = {name: 'value'}; - soap.createClient(url, function(err, client) { - client.MyFunction(args, function(err, result) { - console.log(result); +- Start with the WSDL for the Web Service you want to invoke. For e.g the Weather Web Service http://wsf.cdyne.com/WeatherWS/Weather.asmx and the WSDL is http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL + +- Create a new SOAP client from WSDL url using soap.createClient(url[, options], callback) API. Also supports a local filesystem path. An instance of `Client` is passed to the `soap.createClient` callback. It is used to execute methods on the soap service. +``` + var soap = require('strong-soap').soap; + //wsdl of the Web Service this client is going to invoke. This can point to local wsdl as well. + var url = 'http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL'; + var requestArgs = { + ZIP: '94306' + }; + var options = {}; + + soap.createClient(url, options, function(err, client) { + client.GetCityWeatherByZIP(requestArgs, function(err, result, envelope) { + //response envelope + console.log(envelope); + //result in SOAP envelope body which is the wrapper element. In this case, result object corresponds to GetCityForecastByZIPResponse + console.log(JSON.stringify(result)); + }); }); - }); ``` - -#### Options +The Request envelope created by above service invocation. + ``` +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> + <soap:Header/> + <soap:Body> + <ns1:GetCityWeatherByZIP xmlns:ns1="http://ws.cdyne.com/WeatherWS/"> + <ns1:ZIP>94306</ns1:ZIP> + </ns1:GetCityWeatherByZIP> + </soap:Body> +</soap:Envelope> + ``` +This WSDL operation is defined as document/literal-wrapped style. Hence the request in soap <Body> is wrapped in operation name. Refer to test cases [server-client-document-test](https://github.com/strongloop/strong-soap/blob/master/test/server-client-document-test.js) and [server-client-rpc-test](https://github.com/strongloop/strong-soap/blob/master/test/server-client-rpc-test.js) to understand document and rpc styles and their +Request, Response and Fault samples. The `options` argument allows you to customize the client with the following properties: - endpoint: to override the SOAP service's host specified in the `.wsdl` file. - request: to override the [request](https://github.com/request/request) module. - httpClient: to provide your own http client that implements `request(rurl, data, callback, exheaders, exoptions)`. -- forceSoap12Headers: to set proper headers for SOAP v1.2 - envelopeKey: to set specific key instead of <pre><<b>soap</b>:Body></<b>soap</b>:Body></pre> - wsdl_options: custom options for the request module on WSDL requests. - wsdl_headers: custom HTTP headers to be sent on WSDL requests. Note: for versions of node >0.10.X, you may need to specify `{connection: 'keep-alive'}` in SOAP headers to avoid truncation of longer chunked responses. -### soap.listen(*server*, *path*, *services*, *wsdl*) - create a new SOAP server that listens on *path* and provides *services*. -*wsdl* is an xml string that defines the service. - -``` javascript - var myService = { - MyService: { - MyPort: { - MyFunction: function(args) { - return { - name: args.name - }; - }, - - // This is how to define an asynchronous function. - MyAsyncFunction: function(args, callback) { - // do some work - callback({ - name: args.name - }); - }, - - // This is how to receive incoming headers - HeadersAwareFunction: function(args, cb, headers) { - return { - name: headers.Token - }; - }, - - // You can also inspect the original `req` - reallyDeatailedFunction: function(args, cb, headers, req) { - console.log('SOAP `reallyDeatailedFunction` request from ' + req.connection.remoteAddress); - return { - name: headers.Token - }; - } - } - } - }; - - var xml = require('fs').readFileSync('myservice.wsdl', 'utf8'), - server = http.createServer(function(request,response) { - response.end("404: Not Found: " + request.url); - }); - - server.listen(8000); - soap.listen(server, '/wsdl', myService, xml); -``` - -### Options -You can pass in server and [WSDL Options](#handling-xml-attributes-value-and-xml-wsdloptions) -using an options hash. - -``` javascript -var xml = require('fs').readFileSync('myservice.wsdl', 'utf8'); - -soap.listen(server, { - // Server options. - path: '/wsdl', - services: myService, - xml: xml, - - // WSDL options. - attributesKey: 'theAttrs', - valueKey: 'theVal', - xmlKey: 'theXml' -}); -``` - -### Server Logging - -If the `log` method is defined it will be called with 'received' and 'replied' -along with data. - -``` javascript - server = soap.listen(...) - server.log = function(type, data) { - // type is 'received' or 'replied' - }; -``` - -### Server Events - -Server instances emit the following events: - -* request - Emitted for every received messages. - The signature of the callback is `function(request, methodName)`. -* headers - Emitted when the SOAP Headers are not empty. - The signature of the callback is `function(headers, methodName)`. - -The sequence order of the calls is `request`, `headers` and then the dedicated -service method. - -### SOAP Fault - -A service method can reply with a SOAP Fault to a client by `throw`ing an -object with a `Fault` property. - -``` javascript - throw { - Fault: { - Code: { - Value: "soap:Sender", - Subcode: { value: "rpc:BadArguments" } - }, - Reason: { Text: "Processing Error" } - } - }; -``` - -To change the HTTP statusCode of the response include it on the fault. The statusCode property will not be put on the xml message. - -``` javascript - throw { - Fault: { - Code: { - Value: "soap:Sender", - Subcode: { value: "rpc:BadArguments" } - }, - Reason: { Text: "Processing Error" }, - statusCode: 500 - } - }; -``` -### Server security example using PasswordDigest +### Extra Headers (optional) -If `server.authenticate` is not defined then no authentication will take place. +User can define extra HTTP headers to be sent on the request. -``` javascript - server = soap.listen(...) - server.authenticate = function(security) { - var created, nonce, password, user, token; - token = security.UsernameToken, user = token.Username, - password = token.Password, nonce = token.Nonce, created = token.Created; - return user === 'user' && password === soap.passwordDigest(nonce, created, 'password'); - }; ``` - -### Server connection authorization - -The `server.authorizeConnection` method is called prior to the soap service method. -If the method is defined and returns `false` then the incoming connection is -terminated. - -``` javascript - server = soap.listen(...) - server.authorizeConnection = function(req) { - return true; // or false - }; + soap.createClient(url, clientOptions, function(err, client) { + //custom request header + var customRequestHeader = {customheader1: 'test1'}; + client.GetCityWeatherByZIP(requestArgs, function(err, result, envelope) { + //result in SOAP envelope body which is the wrapper element. In this case, result object corresponds to GetCityForecastByZIPResponse + console.log(JSON.stringify(result)); + }, null, customRequestHeader); + }); ``` - -## SOAP Headers - -### Received SOAP Headers - -A service method can look at the SOAP headers by providing a 3rd arguments. +### Client.describe() - description of services, ports and methods as a JavaScript object ``` javascript - { - HeadersAwareFunction: function(args, cb, headers) { - return { - name: headers.Token - }; - } - } + //this describes the entire WSDL in a JSON tree object form. + var description = client.describe(); + //inspect GetCityWeatherByZIP operation. You can inspect Service: {Port: {operation: { + console.log(JSON.stringify(description.Weather.WeatherSoap.GetCityWeatherByZIP)); ``` -It is also possible to subscribe to the 'headers' event. -The event is triggered before the service method is called, and only when the -SOAP Headers are not empty. -``` javascript - server = soap.listen(...) - server.on('headers', function(headers, methodName) { - // It is possible to change the value of the headers - // before they are handed to the service method. - // It is also possible to throw a SOAP Fault - }); -``` - -First parameter is the Headers object; -second parameter is the name of the SOAP method that will called -(in case you need to handle the headers differently based on the method). - -### Outgoing SOAP Headers - -Both client & server can define SOAP headers that will be added to what they send. -They provide the following methods to manage the headers. - - -#### *addSoapHeader*(soapHeader[, name, namespace, xmlns]) - add soapHeader to soap:Header node -##### Parameters - - `soapHeader` Object({rootName: {name: "value"}}) or strict xml-string - -##### Returns -The index where the header is inserted. - -##### Optional parameters when first arg is object : - - `name` Unknown parameter (it could just a empty string) - - `namespace` prefix of xml namespace - - `xmlns` URI - -#### *changeSoapHeader*(index, soapHeader[, name, namespace, xmlns]) - change an already existing soapHeader -##### Parameters - - `index` index of the header to replace with provided new value - - `soapHeader` Object({rootName: {name: "value"}}) or strict xml-string - -#### *getSoapHeaders*() - return all defined headers - -#### *clearSoapHeaders*() - remove all defined headers - - -## Client - -An instance of `Client` is passed to the `soap.createClient` callback. It is used to execute methods on the soap service. - -### Client.describe() - description of services, ports and methods as a JavaScript object +### Client.setSecurity(security) - use the specified security protocol -``` javascript - client.describe() // returns - { - MyService: { - MyPort: { - MyFunction: { - input: { - name: 'string' - } - } - } - } - } -``` +Refer to test case [ssl-test](https://github.com/strongloop/strong-soap/blob/master/test/ssl-test.js) for this API usage. -### Client.setSecurity(security) - use the specified security protocol ### Client.*method*(args, callback) - call *method* on the SOAP service. ``` javascript - client.MyFunction({name: 'value'}, function(err, result, raw, soapHeader) { + client.MyFunction({name: 'value'}, function(err, result, envelope, soapHeader) { // result is a javascript object - // raw is the raw response + // envelope is the response envelope from the Web Service // soapHeader is the response soap header as a javascript object }) ``` @@ -347,6 +164,7 @@ An instance of `Client` is passed to the `soap.createClient` callback. It is us ``` #### Options (optional) + - Accepts any option that the request module accepts, see [here.](https://github.com/mikeal/request) - For example, you could set a timeout of 5 seconds on the request like this: ``` javascript @@ -362,13 +180,10 @@ An instance of `Client` is passed to the `soap.createClient` callback. It is us }, {time: true}) ``` -#### Extra Headers (optional) - -Object properties define extra HTTP headers to be sent on the request. #### Alternative method call using callback-last pattern -To align method call signature with node' standard callback-last patter and event allow promisification of method calls, the following method signatures are also supported: +To align method call signature with node' standard callback-last pattern and event allow promisification of method calls, the following method signatures are also supported: ```javascript client.MyService.MyPort.MyFunction({name: 'value'}, options, function (err, result) { @@ -380,26 +195,13 @@ client.MyService.MyPort.MyFunction({name: 'value'}, options, extraHeaders, funct }) ``` -###Overriding the namespace prefix -`strong-soap` is still working out some kinks regarding namespaces. If you find that an element is given the wrong namespace prefix in the request body, you can add the prefix to it's name in the containing object. I.E.: +### Client.*lastRequest* -```javascript - client.MyService.MyPort.MyFunction({'ns1:name': 'value'}, function(err, result) { - // request body sent with `<ns1:name`, regardless of what the namespace should have been. - }, {timeout: 5000}) -``` +The property that contains last full soap request for client logging -- Remove namespace prefix of param +### Client.setEndpoint(url) -```javascript - client.MyService.MyPort.MyFunction({':name': 'value'}, function(err, result) { - // request body sent with `<name`, regardless of what the namespace should have been. - }, {timeout: 5000}) -``` - -### Client.*lastRequest* - the property that contains last full soap request for client logging - -### Client.setEndpoint(url) - overwrite the SOAP service endpoint address +Overwrites the SOAP service endpoint address ### Client Events Client instances emit the following events: @@ -414,7 +216,24 @@ Soap body contents. Useful if you don't want to log /store Soap headers. the SOAP response body as well as the entire `IncomingMessage` response object. This is emitted for all responses (both success and errors). -## Security +``` +Refer to test case [ssl-test](https://github.com/strongloop/strong-soap/blob/master/test/client-test.js) for the usage. Here is one example of 'soapError' event + + soap.createClient(__dirname + '/wsdl/default_namespace.wsdl', function (err, client) { + var didEmitEvent = false; + client.on('soapError', function(err) { + didEmitEvent = true; + assert.ok(err.root.Envelope.Body.Fault); + }); + client.MyOperation({}, function(err, result) { + assert.ok(didEmitEvent); + done(); + }); + }, baseUrl); +``` + + +### Security `strong-soap` has several default security protocols. You can easily add your own as well. The interface is quite simple. Each protocol defines 2 methods: @@ -474,9 +293,10 @@ WS-Security X509 Certificate support. client.setSecurity(wsSecurity); ``` -_Note_: Optional dependency 'ursa' is required to be installed succefully when WSSecurityCert is used. +_Note_: Optional dependency 'ursa' is required to be installed successfully when WSSecurityCert is used. -## Handling XML Attributes, Value and XML (wsdlOptions). +## XML Attributes +### Handling XML Attributes, Value and XML (wsdlOptions) Sometimes it is necessary to override the default behaviour of `strong-soap` in order to deal with the special requirements of your code base or a third library you use. Therefore you can use the `wsdlOptions` Object, which is passed in the `#createClient()` method and could have any (or all) of the following contents: @@ -487,9 +307,10 @@ var wsdlOptions = { xmlKey: 'theXml' } ``` -If nothing (or an empty Object `{}`) is passed to the `#createClient()` method, the `strong-soap` defaults (`attributesKey: 'attributes'`, `valueKey: '$value'` and `xmlKey: '$xml'`) are used. -###Overriding the `value` key +If nothing (or an empty Object `{}`) is passed to the `#createClient()` method, the `strong-soap` defaults (`attributesKey: '$attributes'`, `valueKey: '$value'` and `xmlKey: '$xml'`) are used. + +### Overriding the value key By default, `strong-soap` uses `$value` as key for any parsed XML value which may interfere with your other code as it could be some reserved word, or the `$` in general cannot be used for a key to start with. @@ -504,7 +325,7 @@ soap.createClient(__dirname + '/wsdl/default_namespace.wsdl', wsdlOptions, funct }); ``` -###Overriding the `xml` key +### Overriding the xml key As `valueKey`, `strong-soap` uses `$xml` as key. The xml key is used to pass XML Object without adding namespace or parsing the string. Example : @@ -534,7 +355,7 @@ soap.createClient(__dirname + '/wsdl/default_namespace.wsdl', wsdlOptions, funct }); ``` -###Overriding the `attributes` key +### Overriding the `attributes` key You can achieve attributes like: ``` xml <parentnode> @@ -547,7 +368,7 @@ By attaching an attributes object to a node. { parentnode: { childnode: { - attributes: { + $attributes: { name: 'childsname' } } @@ -566,99 +387,362 @@ var wsdlOptions = { attributesKey: '$attributes' }; +``` + +Adding xsiType + +``` soap.createClient(__dirname + '/wsdl/default_namespace.wsdl', wsdlOptions, function (err, client) { client.*method*({ parentnode: { childnode: { $attributes: { - name: 'childsname' + $xsiType: "{xmlnsTy}Ty" } } } }); }); ``` -### Specifying the exact namespace definition of the root element -In rare cases, you may want to precisely control the namespace definition that is included in the root element. -You can specify the namespace definitions by setting the overrideRootElement key in the `wsdlOptions` like so: -```javascript -var wsdlOptions = { - "overrideRootElement": { - "namespace": "xmlns:tns", - "xmlnsAttributes": [{ - "name": "xmlns:ns2", - "value": "http://tempuri.org/" - }, { - "name": "xmlns:ns3", - "value": "http://sillypets.com/xsd" - }] - } -}; +Removing the xsiType. The resulting Request shouldn't have the attribute xsiType + +``` +soap.createClient(__dirname + '/wsdl/default_namespace.wsdl', wsdlOptions, function (err, client) { + client.*method*({ + parentnode: { + childnode: { + $attributes: { + + } + } + } + }); +}); ``` -To see it in practice, consider the sample files in: [test/request-response-samples/addPets__force_namespaces](https://github.com/strongloop/strong-soap/tree/master/test/request-response-samples/addPets__force_namespaces) +To see it in practice, consider the sample in: [test/request-response-samples/addPets__force_namespaces](https://github.com/strongloop/strong-soap/tree/master/test/request-response-samples/addPets__force_namespaces) +## XMLHandler +XMLHandler provides capabilities for the user to convert JSON object to XML and XML to JSON object. It also provides capability to Parse XML string or stream into the XMLBuilder tree. -## Handling "ignored" namespaces -If an Element in a `schema` definition depends on an Element which is present in the same namespace, normally the `tns:` -namespace prefix is used to identify this Element. This is not much of a problem as long as you have just one `schema` defined -(inline or in a separate file). If there are more `schema` files, the `tns:` in the generated `soap` file resolved mostly to the parent `wsdl` file, - which was obviously wrong. +- API to Convert JSON object to XML and XML to JSON object. - `strong-soap` now handles namespace prefixes which shouldn't be resolved (because it's not necessary) as so called `ignoredNamespaces` - which default to an Array of 3 Strings (`['tns', 'targetNamespace', 'typedNamespace']`). +``` + var soap = require('..').soap; + var XMLHandler = soap.XMLHandler; + var xmlHandler = new XMLHandler(); + var util = require('util'); + + //custom request header + var customRequestHeader = {customheader1: 'test1'}; + var options = {}; + client.GetCityWeatherByZIP(requestArgs, function(err, result, envelope, soapHeader) { + //convert 'result' JSON object to XML + var node = xmlHandler.jsonToXml(null, null, + XMLHandler.createSOAPEnvelopeDescriptor('soap'), result); + var xml = node.end({pretty: true}); + console.log(xml); + + //convert XML to JSON object + var root = xmlHandler.xmlToJson(null, xml, null); + console.log('%s', util.inspect(root, {depth: null})); - If this is not sufficient for your purpose you can easily add more namespace prefixes to this Array, or override it in its entirety - by passing an `ignoredNamespaces` object within the `options` you pass in `soap.createClient()` method. + }, options, customRequestHeader); + }); +``` - A simple `ignoredNamespaces` object, which only adds certain namespaces could look like this: - ``` - var options = { - ignoredNamespaces: { - namespaces: ['namespaceToIgnore', 'someOtherNamespace'] - } - } - ``` - This would extend the `ignoredNamespaces` of the `WSDL` processor to `['tns', 'targetNamespace', 'typedNamespace', 'namespaceToIgnore', 'someOtherNamespace']`. +- Parse XML string or stream into the XMLBuilder tree - If you want to override the default ignored namespaces you would simply pass the following `ignoredNamespaces` object within the `options`: - ``` - var options = { - ignoredNamespaces: { - namespaces: ['namespaceToIgnore', 'someOtherNamespace'], - override: true - } - } - ``` - This would override the default `ignoredNamespaces` of the `WSDL` processor to `['namespaceToIgnore', 'someOtherNamespace']`. (This shouldn't be necessary, anyways). +``` +var root = XMLHandler.parseXml(null, xmlString); +``` - If you want to override the default ignored namespaces you would simply pass the following `ignoredNamespaces` object within the `options`: - ``` - var options = { - ignoredNamespaces: { - namespaces: ['namespaceToIgnore', 'someOtherNamespace'], - override: true - } - } - ``` - This would override the default `ignoredNamespaces` of the `WSDL` processor to `['namespaceToIgnore', 'someOtherNamespace']`. (This shouldn't be necessary, anyways). +## WSDL +### wsdl.open(wsdlURL, options, callback(err, wsdl)) +API to load WSDL into a tree form. User can traverse through WSDL tree to get to bindings, services, ports, operations etc. +##### Parameters + - `wsdlURL` WSDL url to load. + - `options` WSDL options + - `callback` Error and WSDL loaded into object tree. + +``` +var soap = require('..').soap; +var WSDL = soap.WSDL; +var path = require('path'); + +//pass in WSDL options if any + +var options = {}; +WSDL.open('./wsdls/weather.wsdl',options, + function(err, wsdl) { + //user should be able to get to any information of this WSDL from this object. User can traverse + //the WSDL tree and get to bindings, operations, services, portTypes, messages, parts and XSD elements/Attributes. + + var getCityForecastOp = wsdl.definitions.bindings.WeatherSoap.operations.GetCityForecastByZIP; + //print operation name + console.log(getCityForecastOp.name); + var service = wsdl.definitions.services['Weather']; + print service name + console.log(service.name);; +}); +``` + +## Server + +### soap.listen(*server*, *path*, *services*, *wsdl*) - create a new SOAP server that listens on *path* and provides *services*. +*wsdl* is an xml string that defines the service. + +``` javascript + var myService = { + MyService: { + MyPort: { + MyFunction: function(args) { + return { + name: args.name + }; + }, -## Handling "ignoreBaseNameSpaces" attribute -If an Element in a `schema` definition depends has a basenamespace defined but the request does not need that value, for example you have a "sentJob" with basenamespace "v20" -but the request need only: <sendJob> set in the tree structure, you need to set the ignoreBaseNameSpaces to true. This is set because in a lot of workaround the wsdl structure is not correctly -set or the webservice bring errors. + // This is how to define an asynchronous function. + MyAsyncFunction: function(args, callback) { + // do some work + callback({ + name: args.name + }); + }, -By default the attribute is set to true. -An example to use: + // This is how to receive incoming headers + HeadersAwareFunction: function(args, cb, headers) { + return { + name: headers.Token + }; + }, + + // You can also inspect the original `req` + reallyDeatailedFunction: function(args, cb, headers, req) { + console.log('SOAP `reallyDeatailedFunction` request from ' + req.connection.remoteAddress); + return { + name: headers.Token + }; + } + } + } + }; + + var xml = require('fs').readFileSync('myservice.wsdl', 'utf8'), + server = http.createServer(function(request,response) { + response.end("404: Not Found: " + request.url); + }); + + server.listen(8000); + soap.listen(server, '/wsdl', myService, xml); -A simple `ignoredNamespaces` object, which only adds certain namespaces could look like this: ``` -var options = { -ignoredNamespaces: true -} + +Example of SOAP server usage is in [test/server-client-document-test](https://github.com/strongloop/strong-soap/tree/master/test/server-client-document-test.js) + +### Options +You can pass in server and [WSDL Options](#handling-xml-attributes-value-and-xml-wsdloptions) +using an options hash. + +``` javascript +var xml = require('fs').readFileSync('myservice.wsdl', 'utf8'); + +soap.listen(server, { + // Server options. + path: '/wsdl', + services: myService, + xml: xml, + + // WSDL options. + attributesKey: 'theAttrs', + valueKey: 'theVal', + xmlKey: 'theXml' +}); ``` +### Server Logging + +If the `log` method is defined it will be called with 'received' and 'replied' +along with data. + +``` javascript + server = soap.listen(...) + server.log = function(type, data) { + // type is 'received' or 'replied' + }; +``` + +### Server Events + +Server instances emit the following events: + +* request - Emitted for every received messages. + The signature of the callback is `function(request, methodName)`. +* headers - Emitted when the SOAP Headers are not empty. + The signature of the callback is `function(headers, methodName)`. + +The sequence order of the calls is `request`, `headers` and then the dedicated +service method. + +``` + test.soapServer.on('request', function requestManager(request, methodName) { + assert.equal(methodName, 'GetLastTradePrice'); + done(); + }); + +``` + +Example of SOAP server usage in [test/server-test](https://github.com/strongloop/strong-soap/tree/master/test/server-test.js) + +### SOAP Fault + +A service method can reply with a SOAP Fault to a client by `throw`ing an +object with a `Fault` property. + +Example SOAP 1.1 Fault +``` javascript + test.service = { + DocLiteralWrappedService: { + DocLiteralWrappedPort: { + myMethod: function (args, cb, soapHeader) { + throw { + Fault: { + faultcode: "sampleFaultCode", + faultstring: "sampleFaultString", + detail: + { myMethodFault: + {errorMessage: 'MyMethod Business Exception message', value: 10} + } + } + } + } + } + } + } +``` + +SOAP 1.2 Fault + +``` javascript + test.service = { + DocLiteralWrappedService: { + DocLiteralWrappedPort: { + myMethod: function (args, cb, soapHeader) { + throw { + Fault: { + Code: { + Value: "soap:Sender", + Subcode: { Value: "rpc:BadArguments" } + }, + Reason: { Text: "Processing Error" }, + Detail: + {myMethodFault2: + {errorMessage2: 'MyMethod Business Exception message', value2: 10} + } + } + } + } + } + } + } +``` + + +Examples of SOAP 1.1/SOAP 1.2 Fault response can be found in test [test/server-client-document-test](https://github.com/strongloop/strong-soap/tree/master/test/server-client-document-test.js) + +### Server security example using PasswordDigest + +If `server.authenticate` is not defined then no authentication will take place. + +``` javascript + server = soap.listen(...) + server.authenticate = function(security) { + var created, nonce, password, user, token; + token = security.UsernameToken, user = token.Username, + password = token.Password, nonce = token.Nonce, created = token.Created; + return user === 'user' && password === soap.passwordDigest(nonce, created, 'password'); + }; +``` + +### Server connection authorization + +The `server.authorizeConnection` method is called prior to the soap service method. +If the method is defined and returns `false` then the incoming connection is +terminated. + +``` javascript + server = soap.listen(...) + server.authorizeConnection = function(req) { + return true; // or false + }; +``` + + +## SOAP Headers + +### Received SOAP Headers + +A service method can look at the SOAP headers by providing a 3rd arguments. + +``` javascript + { + HeadersAwareFunction: function(args, cb, headers) { + return { + name: headers.Token + }; + } + } +``` + +It is also possible to subscribe to the 'headers' event. +The event is triggered before the service method is called, and only when the +SOAP Headers are not empty. + +``` javascript + server = soap.listen(...) + server.on('headers', function(headers, methodName) { + // It is possible to change the value of the headers + // before they are handed to the service method. + // It is also possible to throw a SOAP Fault + }); +``` + +First parameter is the Headers object; +second parameter is the name of the SOAP method that will called +(in case you need to handle the headers differently based on the method). + +### Outgoing SOAP Headers + +Both client & server can define SOAP headers that will be added to what they send. +They provide the following methods to manage the headers. + + +#### *addSoapHeader*(value, qname) - add soapHeader to soap:Header node +##### Parameters + - `value` JSON object representing {headerName: headerValue} or XML string. + - `qname` qname used for the header + +``` +addSoapHeader(value, qname, options); + +``` + +##### Returns +The index where the header is inserted. + +#### * changeSoapHeader(index, value, qname) - change an already existing soapHeader +##### Parameters + - `index` index of the header to replace with provided new value + - `value` JSON object representing {headerName: headerValue} or XML string. + - `qname` qname used for the header + +#### *getSoapHeaders*() - return all defined headers + +#### *clearSoapHeaders*() - remove all defined headers + +SOAP header API usage can be found in [test/server-test](https://github.com/strongloop/strong-soap/tree/master/test/server-test.js) or [test/server-test](https://github.com/strongloop/strong-soap/tree/master/test/client-test.js) + ## soap-stub Unit testing services that use soap clients can be very cumbersome. In order to get diff --git a/example/json2xml.js b/example/json2xml.js index 17c812f9..a0cb104c 100644 --- a/example/json2xml.js +++ b/example/json2xml.js @@ -1,4 +1,4 @@ -var soap = require('../index'); +var soap = require('..').soap; var XMLHandler = soap.XMLHandler; var xmlHandler = new XMLHandler(); @@ -8,17 +8,17 @@ var json = { Envelope: { Header: undefined, Body: { - IFX_PmtInqRq: { - SignonRq: {ClientApp: {Org: 'IBM', Name: 'TestApp'}}, - BankSvcRq: [{ + BookStore: { + Detail: {StoreDetail: {Name: 'Modern Book Store', Address: '1001 Lane'}}, + Genre: [{ '$attributes': {Id: 'id1'}, - RqUID: '1', - PmtInqRq: {RqUID: '11'} + Aisle: '1', + Name: {Fiction: '11'} }, { '$attributes': {Id: 'id2'}, - RqUID: '2', - PmtInqRq: {RqUID: '22'} + Aisle: '2', + Name: {NonFiction: '22'} }] } } @@ -34,26 +34,26 @@ var xmlString = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header/> <soap:Body> - <com.td.payment:IFX_PmtInqRq xmlns:com.td.payment="http://services.tdgroup.com/ifxpmt/2012/09/10"> - <IFX:SignonRq xmlns:IFX="http://services.tdgroup.com/IFX170_XSD/2008/08/14"> - <IFX:ClientApp> - <IFX:Org>IBM</IFX:Org> - <IFX:Name>TestApp</IFX:Name> - </IFX:ClientApp> - </IFX:SignonRq> - <com.td.payment:BankSvcRq Id="id1"> - <IFX:RqUID>1</IFX:RqUID> - <com.td.payment:PmtInqRq> - <IFX:RqUID>11</IFX:RqUID> - </com.td.payment:PmtInqRq> - </com.td.payment:BankSvcRq> - <com.td.payment:BankSvcRq Id="id2"> - <IFX:RqUID>2</IFX:RqUID> - <com.td.payment:PmtInqRq> - <IFX:RqUID>22</IFX:RqUID> - </com.td.payment:PmtInqRq> - </com.td.payment:BankSvcRq> - </com.td.payment:IFX_PmtInqRq> + <ns1:BookStore xmlns:ns1="http://bookstore.com/"> + <ns2:Detail xmlns:ns2="http://bookstore.com/detail"> + <ns2:StoreDetail> + <ns2:Name>Modern Book Store</ns2:Name> + <ns2:Address>1001 Lane</ns2:Address> + </ns2:StoreDetail> + </ns2:Detail> + <ns1:Genre Id="id1"> + <ns2:Aisle>1</ns2:Aisle> + <ns1:Name> + <ns2:Fiction>11</ns2:Fiction> + </ns1:Name> + </ns1:Genre> + <ns1:Genre Id="id2"> + <ns2:Aisle>2</ns2:Aisle> + <ns1:Name> + <ns2:NonFiction>22</ns2:NonFiction> + </ns1:Name> + </ns1:Genre> + </ns1:BookStore> </soap:Body> </soap:Envelope>`; diff --git a/example/stock.js b/example/stock.js deleted file mode 100644 index fab9e343..00000000 --- a/example/stock.js +++ /dev/null @@ -1,18 +0,0 @@ -var path = require('path'); -var soap = require('../index'); - -soap.createClient(path.join(__dirname, 'wsdls/stockquote.wsdl'), {}, - function(err, client) { - if (err) { - console.error(err); - return; - } - - var req = { - tickerSymbol: 'IBM' - }; - - var method = client['StockQuoteService']['StockQuotePort']['GetLastTradePrice']; - method(req, console.log); - - }); diff --git a/example/weather.js b/example/weather.js index 732c8656..4b722d7a 100644 --- a/example/weather.js +++ b/example/weather.js @@ -1,18 +1,51 @@ -var path = require('path'); -var soap = require('../index'); -soap.createClient(path.join(__dirname, 'wsdls/weather.wsdl'), {}, - function(err, client) { - if (err) { - console.error(err); - return; - } +"use strict"; - var req = { - ZIP: '94555' - }; +var fs = require('fs'), + assert = require('assert'), + request = require('request'), + http = require('http'), + lastReqAddress; +var soap = require('..').soap; +var XMLHandler = soap.XMLHandler; +var xmlHandler = new XMLHandler(); +var util = require('util'); - var method = client['Weather']['WeatherSoap']['GetCityWeatherByZIP']; - method(req, console.log); +//wsdl of the Web Service this client is going to invoke. This can point to local wsdl as well. +var url = 'http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL'; +var requestArgs = { + ZIP: '94306' +}; +var clientOptions = {}; - }); + +soap.createClient(url, clientOptions, function(err, client) { + //custom request header + var customRequestHeader = {timeout: 5000}; + var options = {}; + //you can also call + client.GetCityWeatherByZIP(requestArgs, function(err, result, envelope, soapHeader) { + //response envelope + console.log(envelope); + //result in SOAP envelope body which is the wrapper element. In this case, result object corresponds to GetCityForecastByZIPResponse + console.log(JSON.stringify(result)); + //this describes the entire WSDL in a tree form. + var description = client.describe(); + //inspect GetCityWeatherByZIP operation + var operation = description.Weather.WeatherSoap.GetCityWeatherByZIP; + + var node = xmlHandler.jsonToXml(null, null, + XMLHandler.createSOAPEnvelopeDescriptor('soap'), result); + var xml = node.end({pretty: true}); + console.log(xml); + + var root = xmlHandler.xmlToJson(null, xml, null); + console.log('%s', util.inspect(root, {depth: null})); + + var root = XMLHandler.parseXml(null, xml); + var result = root.end({pretty: true}); + console.log(result); + + + }, null, customRequestHeader); +}); diff --git a/example/wsdl-test.js b/example/wsdl-test.js deleted file mode 100644 index f625762c..00000000 --- a/example/wsdl-test.js +++ /dev/null @@ -1,10 +0,0 @@ -var path = require('path'); -var soap = require('../index'); - -soap.createClient(path.join(__dirname, '../test/wsdl/binding-exception.wsdl'), {}, - function(err, client) { - if (err) { - console.error(err); - return; - } - }); diff --git a/example/wsdl.js b/example/wsdl.js deleted file mode 100644 index 069a0def..00000000 --- a/example/wsdl.js +++ /dev/null @@ -1,63 +0,0 @@ -var path = require('path'); -var soap = require('../index'); -var XMLHandler = soap.XMLHandler; -var NamespaceContext = soap.NamespaceContext; - -soap.createClient(path.join(__dirname, 'wsdls/td.wsdl'), {}, - function(err, client) { - if (err) { - console.error(err); - return; - } - var definitions = client.wsdl.definitions; - var operation = definitions.services['IFX_Payment'] - .ports['Pmt_SoapPort_20120910'].binding.operations['IFX_PaymentAdd']; - - var req = { - IFX_PaymentAdd: { - SignonRq: { - ClientApp: { - Org: 'IBM', - Name: 'TestApp' - } - }, - BankSvcRq: [ - { - RqUID: '1', - PmtInqRq: [{ - RqUID: '2' - }], - $attributes: { - Id: 'id' - } - } - ] - } - }; - - // var method = client['IFX_Payment']['Pmt_SoapPort_20120910']['IFX_PaymentAdd']; - // method(req, console.log); - - console.log(operation.describe(definitions)); - - var ns = 'http://services.tdgroup.com/ifxpmt/2012/09/10'; - var schema = definitions.schemas[ns]; - - var element = schema.elements['IFX_PmtAddRq']; - - var descriptor = element.describe(definitions); - var xmlHandler = new XMLHandler(); - var nsContext = new NamespaceContext(); - for (let prefix in schema.xmlns) { - nsContext.addNamespace(prefix, schema.xmlns[prefix]); - } - - var root = XMLHandler.createSOAPEnvelope(); - - var node = xmlHandler.jsonToXml(root.body, nsContext, descriptor, - req.IFX_PaymentAdd, { - attributesKey: '$attributes' - }); - var xml = node.end({pretty: true}); - console.log(xml); - }); diff --git a/example/wsdls/stockquote.wsdl b/example/wsdls/stockquote.wsdl deleted file mode 100644 index 03b62aa3..00000000 --- a/example/wsdls/stockquote.wsdl +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0"?> - -<wsdl:definitions name="StockQuote" - targetNamespace="http://example.com/stockquote.wsdl" - xmlns:tns="http://example.com/stockquote.wsdl" - xmlns:xsd1="http://example.com/stockquote.xsd" - xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" - xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> - - <wsdl:types> - <xsd:schema targetNamespace="http://example.com/stockquote.xsd" - xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"> - <xsd:element name="TradePriceRequest"> - <xsd:complexType> - <xsd:all> - <xsd:element name="tickerSymbol" type="xsd:string"/> - </xsd:all> - </xsd:complexType> - </xsd:element> - <xsd:element name="TradePrice"> - <xsd:complexType> - <xsd:all> - <xsd:element name="price" type="xsd:float"/> - </xsd:all> - </xsd:complexType> - </xsd:element> - </xsd:schema> - </wsdl:types> - - <wsdl:message name="GetLastTradePriceInput"> - <wsdl:part name="body" element="xsd1:TradePriceRequest"/> - </wsdl:message> - - <wsdl:message name="GetLastTradePriceOutput"> - <wsdl:part name="body" element="xsd1:TradePrice"/> - </wsdl:message> - - <wsdl:portType name="StockQuotePortType"> - <wsdl:operation name="GetLastTradePrice"> - <wsdl:input message="tns:GetLastTradePriceInput"/> - <wsdl:output message="tns:GetLastTradePriceOutput"/> - </wsdl:operation> - </wsdl:portType> - - <wsdl:binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType"> - <soap:binding style="document" - transport="http://schemas.xmlsoap.org/soap/http"/> - <wsdl:operation name="GetLastTradePrice"> - <soap:operation soapAction="http://example.com/GetLastTradePrice"/> - <wsdl:input> - <soap:body use="literal"/> - </wsdl:input> - <wsdl:output> - <soap:body use="literal"/> - </wsdl:output> - </wsdl:operation> - </wsdl:binding> - - <wsdl:service name="StockQuoteService"> - <wsdl:port name="StockQuotePort" binding="tns:StockQuoteSoapBinding"> - <soap:address location="http://localhost:3000/stockquote"/> - </wsdl:port> - </wsdl:service> - -</wsdl:definitions> diff --git a/example/xml.js b/example/xml.js index 1076ce5c..3180fa4d 100644 --- a/example/xml.js +++ b/example/xml.js @@ -1,26 +1,32 @@ -var soap = require('../index'); +var soap = require('..').soap; var XMLHandler = soap.XMLHandler; var xmlString = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"> - <soap11:Header/> - <soap11:Body> - <com.td.payment:IFX_PmtInqRq xmlns:com.td.payment="http://services.tdgroup.com/ifxpmt/2012/09/10"> - <IFX:SignonRq xmlns:IFX="http://services.tdgroup.com/IFX170_XSD/2008/08/14"> - <IFX:ClientApp> - <IFX:Org>IBM</IFX:Org> - <IFX:Name>TestApp</IFX:Name> - </IFX:ClientApp> - </IFX:SignonRq> - <com.td.payment:BankSvcRq Id="id"> - <IFX:RqUID>1</IFX:RqUID> - <com.td.payment:PmtInqRq> - <IFX:RqUID>2</IFX:RqUID> - </com.td.payment:PmtInqRq> - </com.td.payment:BankSvcRq> - </com.td.payment:IFX_PmtInqRq> - </soap11:Body> -</soap11:Envelope>`; +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> + <soap:Header/> + <soap:Body> + <ns1:BookStore xmlns:ns1="http://bookstore.com/"> + <ns2:Detail xmlns:ns2="http://bookstore.com/detail"> + <ns2:StoreDetail> + <ns2:Name>Modern Book Store</ns2:Name> + <ns2:Address>1001 Lane</ns2:Address> + </ns2:StoreDetail> + </ns2:Detail> + <ns1:Genre Id="id1"> + <ns2:Aisle>1</ns2:Aisle> + <ns1:Name> + <ns2:Fiction>11</ns2:Fiction> + </ns1:Name> + </ns1:Genre> + <ns1:Genre Id="id2"> + <ns2:Aisle>2</ns2:Aisle> + <ns1:Name> + <ns2:NonFiction>22</ns2:NonFiction> + </ns1:Name> + </ns1:Genre> + </ns1:BookStore> + </soap:Body> +</soap:Envelope>`; var root = XMLHandler.parseXml(null, xmlString); var result = root.end({pretty: true}); diff --git a/example/xml2json.js b/example/xml2json.js index 729ad16a..2f8e1383 100644 --- a/example/xml2json.js +++ b/example/xml2json.js @@ -1,4 +1,4 @@ -var soap = require('../index'); +var soap = require('..').soap; var XMLHandler = soap.XMLHandler; var xmlHandler = new XMLHandler(); @@ -8,29 +8,30 @@ var xmlString = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header/> <soap:Body> - <com.td.payment:IFX_PmtInqRq xmlns:com.td.payment="http://services.tdgroup.com/ifxpmt/2012/09/10"> - <IFX:SignonRq xmlns:IFX="http://services.tdgroup.com/IFX170_XSD/2008/08/14"> - <IFX:ClientApp> - <IFX:Org>IBM</IFX:Org> - <IFX:Name>TestApp</IFX:Name> - </IFX:ClientApp> - </IFX:SignonRq> - <com.td.payment:BankSvcRq Id="id1"> - <IFX:RqUID>1</IFX:RqUID> - <com.td.payment:PmtInqRq> - <IFX:RqUID>11</IFX:RqUID> - </com.td.payment:PmtInqRq> - </com.td.payment:BankSvcRq> - <com.td.payment:BankSvcRq Id="id2"> - <IFX:RqUID>2</IFX:RqUID> - <com.td.payment:PmtInqRq> - <IFX:RqUID>22</IFX:RqUID> - </com.td.payment:PmtInqRq> - </com.td.payment:BankSvcRq> - </com.td.payment:IFX_PmtInqRq> + <ns1:BookStore xmlns:ns1="http://bookstore.com/"> + <ns2:Detail xmlns:ns2="http://bookstore.com/detail"> + <ns2:StoreDetail> + <ns2:Name>Modern Book Store</ns2:Name> + <ns2:Address>1001 Lane</ns2:Address> + </ns2:StoreDetail> + </ns2:Detail> + <ns1:Genre Id="id1"> + <ns2:Aisle>1</ns2:Aisle> + <ns1:Name> + <ns2:Fiction>11</ns2:Fiction> + </ns1:Name> + </ns1:Genre> + <ns1:Genre Id="id2"> + <ns2:Aisle>2</ns2:Aisle> + <ns1:Name> + <ns2:NonFiction>22</ns2:NonFiction> + </ns1:Name> + </ns1:Genre> + </ns1:BookStore> </soap:Body> </soap:Envelope>`; +var xmlString1 = '' var root = xmlHandler.xmlToJson(null, xmlString, null); console.log('%s', util.inspect(root, {depth: null})); diff --git a/example/xsds.js b/example/xsds.js index fcfe2c65..b0eb775a 100644 --- a/example/xsds.js +++ b/example/xsds.js @@ -1,10 +1,16 @@ -var soap = require('../index'); +var soap = require('..').soap; var WSDL = soap.WSDL; +var path = require('path'); -WSDL.loadSystemSchemas(function(err, schemas) { - if (err) { - console.error(err); - } else { - console.log(Object.keys(schemas)); - } -}); + +//user can pass in WSDL options +var options = {}; + +WSDL.open('./wsdls/weather.wsdl', options, + //User can traverse the WSDL tree and get to bindings - > operations, services, portTypes, messages, parts and XSD elements/Attributes + function(err, wsdl) { + var getCityForecastOp = wsdl.definitions.bindings.WeatherSoap.operations.GetCityForecastByZIP; + console.log(getCityForecastOp.name); + var service = wsdl.definitions.services['Weather']; + console.log(service.name);; + }); diff --git a/src/base.js b/src/base.js index d16331e9..90ec4e17 100644 --- a/src/base.js +++ b/src/base.js @@ -14,13 +14,13 @@ class Base extends EventEmitter { this.bodyAttributes = []; } - addSoapHeader(value, qname, options) { - var header = new SOAPElement(value, qname, options); + addSoapHeader(value, qname) { + var header = new SOAPElement(value, qname, null); return this.soapHeaders.push(header) - 1; } - changeSoapHeader(index, value, qname, options) { - var header = new SOAPElement(value, qname, options); + changeSoapHeader(index, value, qname) { + var header = new SOAPElement(value, qname, null); this.soapHeaders[index] = header; } diff --git a/src/parser/wsdl.js b/src/parser/wsdl.js index bc285c75..6eeb58c8 100644 --- a/src/parser/wsdl.js +++ b/src/parser/wsdl.js @@ -143,9 +143,6 @@ class WSDL { // Works only in client this.options.forceSoap12Headers = options.forceSoap12Headers; - if (options.overrideRootElement !== undefined) { - this.options.overrideRootElement = options.overrideRootElement; - } } _processNextInclude(includes, callback) { diff --git a/test/server-client-document-test.js b/test/server-client-document-test.js index c4c4a2b8..a5a53e7f 100644 --- a/test/server-client-document-test.js +++ b/test/server-client-document-test.js @@ -589,6 +589,8 @@ describe('Document style tests', function() { }); }); + + });