fiorix / wsdl2go Goto Github PK
View Code? Open in Web Editor NEWCommand line tool to generate Go code from WSDL for SOAP XML services
License: Other
Command line tool to generate Go code from WSDL for SOAP XML services
License: Other
In Soap1.1, the soapAction header is set to the object's name even if the wsdl specifies the soapAction name.
For example, the following wsdl snippet
<soap:operation soapAction="http://soap.example.com"/>
<soap:body use="literal"/>
<soap:body use="literal"/>
<soap:fault name="WsValidationException" use="literal"/>
will generate
if err = p.cli.RoundTripWithAction("ModifyObj", α, &γ); err != nil {
return nil, err
}
return &γ.Body.M, nil
instead, I should expect
if err = p.cli.RoundTripWithAction("http://soap.example.com", α, &γ); err != nil {
return nil, err
}
return &γ.Body.M, nil
Related to #65 which uses "tns"
The request which was send used "xmlns:ns":
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn:HandleSearch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
but needed "xmlns:tns":
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="urn:HandleSearch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Ultimate goal of this is to have wsdl2go running on a catalog of public and authorized soap providers and compare their output against some golden files that we pre-generate.
Some WSDL files have link on local dependencies(the same directory), like:
<xsd:import namespace="http://test.net/AdminAPI_Admin" schemaLocation="test.net.AdminAPI_Admin.xsd" />
In this case we have the error:
wsdl import: Get test.net.AdminAPI_Admin.wsdl: unsupported protocol scheme ""
If I'm right - this is a error from net/http
Do we need to bug fix something or I can just fast-fix something in my WSDL file?
https://www.w3schools.com/xml/el_choice.asp
you handle sequence, but not xsd:choice
Any object that is enclosed within a choice, end up with an empty object body.
I am trying to use a web service which I have generated some code for, based on the WSDL. The service returns GetResult of the query as a string, which is a string containing XML. This service is query-based so the XML returned in the GetResult is variable depending on which query is used.
My problem is that when I try using this service, GetResult is allways an empty string. The output below is what the result looks like when I run the request in SOAPUI.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetResponse xmlns="http://www.example.com/webservices">
<GetResult>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Table">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<Table diffgr:id="Table1" msdata:rowOrder="0">
<ID>12345</ID>
</Table>
</NewDataSet>
</diffgr:diffgram>
</GetResult>
</GetResponse>
</soap:Body>
</soap:Envelope>
After #75, the generated file contains request that cannot be properly XML encoded.
For example, see https://play.golang.org/p/1aVTcYXYb2j (which is derived from https://raw.githubusercontent.com/fiorix/wsdl2go/master/wsdlgo/testdata/data.golden) - the request cannot be XML encoded.
A small annoyance that I found today. It revolves around enumeration, and how to work with them.
Take the following wsdl snippet:
<xs:simpleType name="country">
<xs:restriction base="xs:string">
<xs:enumeration value="DE"/>
<xs:enumeration value="AT"/>
<xs:enumeration value="CH"/>
<xs:enumeration value="GB"/>
<xs:enumeration value="ES"/>
<xs:enumeration value="FR"/>
<xs:enumeration value="SK"/>
<xs:enumeration value="LU"/>
<xs:enumeration value="PL"/>
<xs:enumeration value="DK"/>
<xs:enumeration value="IT"/>
<xs:enumeration value="CZ"/>
<xs:enumeration value="US"/>
<xs:enumeration value="BE"/>
<xs:enumeration value="NL"/>
<xs:enumeration value="SE"/>
</xs:restriction>
</xs:simpleType>
This gets translated to:
// Country was auto-generated from WSDL.
type country string
// Validate validates country.
func (v country) Validate() bool {
for _, vv := range []string{
"DE",
"AT",
"CH",
"GB",
"ES",
"FR",
"SK",
"LU",
"PL",
"DK",
"IT",
"CZ",
"US",
"BE",
"NL",
"SE",
} {
if reflect.DeepEqual(v, vv) {
return true
}
}
return false
}
The problem is type country string
- as the type starts with lowercase, you effectively cannot access that type outside the package the bindings are generated in (which is especially sour if you need that enumeration for requests).
Now, one could of course simple make it start with uppercase just like all the other types. However, that seems unsafe, as we already have a validate method. What I have in mind instead is something like NewCountry(input string)
, which would take a string (or the equivalent type of the enumeration), instantiate a new instance, run validate, and then return the instance or an error.
Edit: I just realize that this a bad idea, since this method would still return an unexported type - which is deemed bad style. So instead - how about title casing them like the other types, but also providing constants of sorts, so they could be used directly without instantiating?
Thoughts?
Hi, i'm try genearet code form documental wsdl (https://api.reformagkh.ru/api_document_literal/wsdl)
But i'm get error:
> panic: runtime error: invalid memory address or nil pointer dereference
> [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x6eba3b]
>
> goroutine 1 [running]:
> github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genGoOpStruct(0xc420168bb0, 0x94db80, 0xc4201579d0, 0xc42015e000, 0xc4202d4a00, 0x0, 0x0)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1358 +0x11b
> github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).writeGoTypes(0xc420168bb0, 0x94db80, 0xc420156d90, 0xc42015e000, 0x0, 0x0)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1110 +0x82f
> github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).(github.com/fiorix/wsdl2go/wsdlgo.writeGoTypes)-fm(0x94db80, 0xc420156d90, 0xc42015e000, 0x0, 0x0)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:208 +0x48
> github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).encode(0xc420168bb0, 0x94db80, 0xc420156d20, 0xc42015e000, 0x80, 0xc420128e40)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:220 +0x370
> github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).Encode(0xc420168bb0, 0xc42015e000, 0xc42027f1d0, 0x0)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:145 +0xa4
> main.codegen(0x94e680, 0xc42000e018, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
> /home/neroot/go/src/github.com/fiorix/wsdl2go/main.go:86 +0x468
> main.main()
> /home/neroot/go/src/github.com/fiorix/wsdl2go/main.go:57 +0x3ce
>
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.2 LTS
Release: 16.04
Codename: xenial
Caused by e0dbfba
$ wsdl2go < search.wsdl > asd.go
panic: interface conversion: http.RoundTripper is nil, not *http.Transport
goroutine 1 [running]:
main.httpClient(...)
/home/fkinder/go/src/github.com/fiorix/wsdl2go/main.go:99
main.main()
/home/fkinder/go/src/github.com/fiorix/wsdl2go/main.go:53 +0x4f6
I ran into the problem, that the response couldn't be unmarshaled, because you apparently assume, that the OutputType
token generated in line https://github.com/fiorix/wsdl2go/blob/master/wsdlgo/encoder.go#L490 as xml:\"{{.OutputType}}\"
is equal for the struct name and in the annotation, which is not the case for my wsdl endpoint. In my case the name of the XML node is not capitalised.
After I changed the xml annotation token to lower-case, the response could be successfully parsed.
I could try to come up with a patch if you'd help me to understand the problem.
Thank you for your work!
Some endpoints require namespaced messages, for example...
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://example.com/WatWebServiceAPI?wsdl">
<SOAP-ENV:Body>
<mns1:watsay xmlns:mns1="http://WatWebServiceAPI/">
<somevalue>WAT</somevalue>
</mns1:watsay>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
instead of (note the watsay
entity)
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://example.com/WatWebServiceAPI?wsdl">
<SOAP-ENV:Body>
<watsay xmlns="http://WatWebServiceAPI/">
<somevalue>WAT</somevalue>
</watsay>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This seems to be the case when the WSDL specifies the targetNamespace
and xmlns:tns
in the wsdl:definitions
entity. I may be wrong on the actual reason for this.
Example snippet from WSDL.
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="WatWebServiceAPI/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="WatWebServiceAPI/"
name="WatService">
<wsdl:types>
...
I noticed a few missing types in the generated code after running my WSDL through your library.
WSDL seems like it makes a distinction distinguish between xs:int
(int32) and xs:integer
(arbitrarily large integer), but you don't support the latter. I think we could just use math/big.Int for these, though we'd have to keep track before outputting the imports.
Additionally, you don't generate any structs for abstract types (https://github.com/fiorix/wsdl2go/blob/master/wsdlgo/encoder.go#L897), which seems odd to me - if any types depend on these, we end up with compile failures, because it doesn't exist. Was there a reason not to emit types that are abstract?
The same thing goes for AnySimpleType
,
http://search.cpan.org/dist/SOAP-WSDL/lib/SOAP/WSDL/XSD/Typelib/Builtin.pm#SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType, but I admit that I don't fully understand the SOAP spec, so I'm not clear what it should convert to.
I'm happy to submit PRs for these small changes, but I wasn't sure if there was a reason behind doing them this way, so I didn't want to jump the gun. Suggestions/fixes would be appreciated. Thanks!
I've got this wsdl file: http://pardano.com/p/webservice/?wsdl
And when I try to run wsdl2go on this file, it sticks on line 71 of main.go (this line)
Any Idea why?
Thanks for wsdl2go!
So, I used wsdl2go and generated awesome set of types for my huge wsdl (which I cannot post here.) However, the service I am trying to hit expects certain custom headers to be present. I can set them in any of my SOAP clients that I use and it goes fine. But, I did not find how to set those headers. I wrote a simple go test like so:
func TestMakeClient(t *testing.T) {
request := new(MyDoSomethingRequest)
client := soap.Client{
URL: "<valid-url-here>",
Namespace: Namespace,
ContentType: "text/xml",
}
svcPort := NewMyServicePort(&client)
resp, err := svcPort.MyDoSomething(request)
if err != nil {
t.Fatalf("nil response received. %s", err.Error())
}
}
I get back errors from my service saying certain headers missing. How do I get a hook to set headers in soap.Client.Config
http
client? Thanks!
Hello,
executing wsdl2go with a valid wsdl shows me the following error:
./wsdl2go < perfilamiento.wsdl > perf1.go
panic: interface conversion: http.RoundTripper is nil, not *http.Transport
goroutine 1 [running]:
panic(0x7ff9a0, 0xc820118480)
/usr/lib/go-1.6/src/runtime/panic.go:481 +0x3e6
main.main()
/home/lalanne/go/src/github.com/fiorix/wsdl2go/main.go:53 +0x5bd
any ideas?
Thanks
From my wsdl, I have one of the operations in types.go
generated like so for one myOperation
:
type MyServicePort interface {
// MyOperation was auto-generated from WSDL.
func (p *myServicePort) MyOperation(α *MyOperationRequest) (β *MyOperationResponse, err error) {
γ := struct {
XMLName xml.Name `xml:"Envelope"`
Body struct {
M MyOperationResponse `xml:"MyOperationResponse"`
}
}{}
if err = p.cli.RoundTrip(α, &γ); err != nil {
return nil, err
}
return &γ.Body.M, nil
}
}
The response type is like so:
type MyOperationResponse struct {
Ack string `xml:"ack,omitempty" json:"ack,omitempty" yaml:"ack,omitempty"`
... // more omitted
}
Server returns XML response for myOperation
like so:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header />
<soapenv:Body>
<myOperation xmlns="http://www.my.com/somenamespace">
<ack>Failure</ack>
<!-- omitted -->
</myOperation>
</soapenv:Body>
</soapenv:Envelope>
Please note, that the case for myOperation
is different from what is defined in the γ struct
in func MyOperation(...)
Now, upon calling MyOperation
always an empty response object is returned. No errors too. Turns out, if I change the case of xml:"MyOperation"
to xml:"myOperation"
in generated types go file - parsing works fine and I get back a response object with all fields set properly. My question is: is this case mismatch while generating code ? or Is something wrong with my wsdl ?
thanks!
Just playing with this library. Ran into an issue here and can't figure out why its failing.
https://gist.github.com/dimitertodorov/a8f42549484132cc9ace61f65dafcf71
Getting the following error.
2016/09/30 10:22:03 template: interfaceType:11:2: executing "interfaceType" at <.Doc>: can't evaluate field Doc in type *wsdlgo.interfaceTypeFunc
exit status 1
I'm trying to process the wsdl from https://testing.maventa.com/apis/v1.1/wsdl. Unfortunately I'm seeing a panic:
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0x6b6a40, 0xc42000c1b0)
/home/vagrant/.local/share/umake/go/go-lang/src/runtime/panic.go:500 +0x1a1
maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).writeInterfaceFuncs(0xc4201f0720, 0x842940, 0xc4201773b0, 0xc4200ee000, 0xc42022ad01, 0xc420222aa0)
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:296 +0x900
maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).(maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo.writeInterfaceFuncs)-fm(0x842940, 0xc4201773b0, 0xc4200ee000, 0x0, 0x4)
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:137 +0x48
maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).encode(0xc4201f0720, 0x842940, 0xc420177340, 0xc4200ee000, 0xc420072a14, 0x1)
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:150 +0x3bc
maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).Encode(0xc4201f0720, 0xc4200ee000, 0xc4202076e0, 0x0)
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:91 +0xbe
main.decode(0x843480, 0xc42002c010, 0x0, 0x0, 0x863600, 0x15, 0x1e)
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/main.go:74 +0x3fc
main.main()
/home/vagrant/dev/grpc-demo/src/maventa/vendor/github.com/fiorix/wsdl2go/main.go:53 +0x210
According to https://golang.org/doc/install, GOROOT should be set only in the case where go binary distribution is installed to a custom location. Otherwise, "The Go binary distributions assume they will be installed in /usr/local/go (or c:\Go under Windows)"
However, in wsdlgo/encoder.go, it requires GOROOT to be set. A better solution is to assume /usr/local/go (or C:\Go in the case of windows) if GOROOT is not set.
The encoder should not encode the SetXMLType object if the complexType itself is abstract. Otherwise, the generated go file cannot compile because you cannot assign TypeAttrXSI and TypeNamespace to it.
Currently, the following is generated:
// BulkOperationRequest was auto-generated from WSDL.
type BulkOperationRequest interface{}// SetXMLType was auto-generated from WSDL.
func (t *BulkOperationRequest) SetXMLType() {
t.TypeAttrXSI = "objtype:BulkOperationRequest"
t.TypeNamespace = "http://www.example.com"
}
I try to invoke wsdl2go -i -o ~/dummy.go
If ~/dummy.go is not present, the program will output
016/09/01 17:50:21 open /home/atam/dummy.go: no such file or directory
Simple fix is to create the file if it not present.
We should add golint in travis and fix all existing golint issues.
When wsdl2go produce the file, it added the Decimal type but it doesnt exists in library.
if you have a problem like me, only add below type definition line on top of the produced file and it works.
type Decimal float32
or on encoder.go change wsdl2goType function like this
// Converts types from wsdl type to Go type.
func (ge *goEncoder) wsdl2goType(t string) string {
// TODO: support other types.
v := ge.trimns(t)
if _, exists := ge.stypes[v]; exists {
return v
}
switch strings.ToLower(v) {
case "int":
return "int"
case "long":
return "int64"
case "float", "double":
return "float64"
case "decimal":
return "float32"
case "boolean":
return "bool"
case "hexbinary", "base64binary":
return "[]byte"
case "string", "anyuri", "token", "qname":
return "string"
case "date":
ge.needsDateType = true
return "Date"
case "time":
ge.needsTimeType = true
return "Time"
case "nonnegativeinteger":
return "uint"
case "datetime":
ge.needsDateTimeType = true
return "DateTime"
case "duration":
ge.needsDurationType = true
return "Duration"
case "anysequence":
return "interface{}"
default:
return "*" + strings.Title(strings.Replace(v, ".", "", -1))
}
}
@kernle32dll the last changes you did in #75 causes:
2017/12/29 10:24:37 generated bad code: 104:11: expected expression (and 1 more errors)
1 package brokerbin
2
3 import (
4 "github.com/fiorix/wsdl2go/soap"
5 )
6
7 // Namespace was auto-generated from WSDL.
8 var Namespace = "urn:HandleSearch"
9
10
11 // NewHandleSearchPort creates an initializes a HandleSearchPort.
12 func NewHandleSearchPort(cli *soap.Client) HandleSearchPort {
13 return &handleSearchPort{cli}
14 }
15
16 // HandleSearchPort was auto-generated from WSDL
17 // and defines interface for the remote service. Useful for testing.
18 type HandleSearchPort interface {
19 // Authenticate was auto-generated from WSDL.
20 Authenticate(reqUsername string,reqPassword string,reqOptions interface{}) (string,error)
21
22 // Search was auto-generated from WSDL.
23 Search(reqPart interface{},reqOptions interface{}) (interface{},error)
24
25 }
26 // Operation wrapper for Authenticate.
27 // OperationAuthenticateRequest was auto-generated from WSDL.
28 type OperationAuthenticateRequest struct {
29 ReqUsername *string `xml:"reqUsername,omitempty" json:"reqUsername,omitempty" yaml:"reqUsername,omitempty"`
30 ReqPassword *string `xml:"reqPassword,omitempty" json:"reqPassword,omitempty" yaml:"reqPassword,omitempty"`
31 ReqOptions *interface{} `xml:"reqOptions,omitempty" json:"reqOptions,omitempty" yaml:"reqOptions,omitempty"`
32 }
33
34 // Operation wrapper for Authenticate.
35 // OperationAuthenticateResponse was auto-generated from WSDL.
36 type OperationAuthenticateResponse struct {
37 ResSession *string `xml:"resSession,omitempty" json:"resSession,omitempty" yaml:"resSession,omitempty"`
38 }
39
40 // Operation wrapper for Search.
41 // OperationSearchRequest was auto-generated from WSDL.
42 type OperationSearchRequest struct {
43 ReqPart *interface{} `xml:"reqPart,omitempty" json:"reqPart,omitempty" yaml:"reqPart,omitempty"`
44 ReqOptions *interface{} `xml:"reqOptions,omitempty" json:"reqOptions,omitempty" yaml:"reqOptions,omitempty"`
45 }
46
47 // Operation wrapper for Search.
48 // OperationSearchResponse was auto-generated from WSDL.
49 type OperationSearchResponse struct {
50 ResParam *interface{} `xml:"resParam,omitempty" json:"resParam,omitempty" yaml:"resParam,omitempty"`
51 }
52
53
54 // handleSearchPort implements the HandleSearchPort interface.
55 type handleSearchPort struct {
56 cli *soap.Client
57 }
58
59 // Authenticate was auto-generated from WSDL.
60 func (p *handleSearchPort) Authenticate(reqUsername string,reqPassword string,reqOptions interface{}) (string,error) {
61 α := struct {
62
63 M OperationAuthenticateRequest `xml:"tns:Authenticate"`
64
65 }{
66 OperationAuthenticateRequest {
67 &reqUsername,
68 &reqPassword,
69 &reqOptions,
70
71 },
72 }
73
74 γ := struct {
75
76 M OperationAuthenticateResponse `xml:"AuthenticateResponse"`
77
78 }{}
79 if err := p.cli.RoundTripWithAction("urn:brokerbin#HandleSearch#Authenticate", α, &γ); err != nil {
80 return "",err
81 }
82 return *γ.M.ResSession, nil
83 }
84 // Search was auto-generated from WSDL.
85 func (p *handleSearchPort) Search(reqPart interface{},reqOptions interface{}) (interface{},error) {
86 α := struct {
87
88 M OperationSearchRequest `xml:"tns:Search"`
89
90 }{
91 OperationSearchRequest {
92 &reqPart,
93 &reqOptions,
94
95 },
96 }
97
98 γ := struct {
99
100 M OperationSearchResponse `xml:"SearchResponse"`
101
102 }{}
103 if err := p.cli.RoundTripWithAction("urn:brokerbin#HandleSearch#Search", α, &γ); err != nil {
104 return &interface{}{},err
105 }
106 return *γ.M.ResParam, nil
107 }
It worked until here: #75 (comment)
wsdl file in #65
In wsdl2go/wsdlgo/encoder.go at line 1040 there is a code:
if el.Type == "" {
el.Type = "string"
}
var slicetype string
if el.Type == "" && el.ComplexType != nil {
...
}
Second "if" will never evaluate to true because when el.Type is empty it'll be set to "string" in the first "if". That will generated all nested complex types as "string" instead of proper types.
Possibly the proper logic should be:
if el.Type == "" {
if el.ComplexType != nil {
...
} else {
el.Type = "string"
}
}
2016/11/20 23:26:37 generated bad code: 1:21: expected ';', found '.'
1 package candidatesxs.cfcsoapbinding
According to this commit you have removed the body
from the soap messages:
It has basically broken the whole functionality over old SOAP servers
I think it should be fixed somehow
The generated go file has the interface name identical to struct name. They should be different instead.
The comment for interface has the word interface appended to the name.
Currently, the SetXMLType function will set the TypeAttrXSI and TypeNamespace for complex content. However, it does not allow the caller to overwrite the above values. In some cases, it will be useful to allow the caller to overwrite these values.
wsdl: http://soap.brokerbin.com/brokerbin_search/search.wsdl
Cut from generated go file:
// NewHandleSearchPort creates an initializes a HandleSearchPort.
func NewHandleSearchPort(cli *soap.Client) HandleSearchPort {
return &handleSearchPort{cli}
}
// HandleSearchPort was auto-generated from WSDL
// and defines interface for the remote service. Useful for testing.
type HandleSearchPort interface {
}
// handleSearchPort implements the HandleSearchPort interface.
type handleSearchPort struct {
cli *soap.Client
}
// Authenticate was auto-generated from WSDL.
func (p *handleSearchPort) Authenticate(α string, reqPassword string, reqOptions interface{}) (β string, err error) {
γ := struct {
XMLName xml.Name `xml:"Envelope"`
Body struct {
M string `xml:"string"`
}
}{}
if err = p.cli.RoundTripWithAction("Authenticate", α, &γ); err != nil {
return "", err
}
return γ.Body.M, nil
}
// Search was auto-generated from WSDL.
func (p *handleSearchPort) Search(α interface{}, reqOptions interface{}) (β interface{}, err error) {
γ := struct {
XMLName xml.Name `xml:"Envelope"`
Body struct {
M interface{} `xml:"interface{}"`
}
}{}
if err = p.cli.RoundTripWithAction("Search", α, &γ); err != nil {
return nil, err
}
return γ.Body.M, nil
}
HandleSearchPort
is empty which causes:
Authenticate
and Search
will only transport first parameter e.g. for Authenticate
:
POST / HTTP/1.1
Host: localhost
Content-Type: text/xml
Soapaction: urn:HandleSearch/Authenticate
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn:HandleSearch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><SOAP-ENV:Body><Message>foo</Message></SOAP-ENV:Body></SOAP-ENV:Envelope>
Expected or needed request for linked wsdl above:
POST / HTTP/1.1
Host: localhost
Content-Type: text/xml
Soapaction: urn:HandleSearch/Authenticate
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:HandleSearch">
<soap:Body>
<tns:Authenticate>
<reqUsername>foo</reqUsername>
<reqPassword>:)</reqPassword>
</tns:Authenticate>
</soap:Body>
</soap:Envelope>
The main difference is that Message
(in first) is replaced by a "message" tns:Authenticate
(in second) which also contains reqUsername
(aka α
) and reqPassword
(aka reqPassword
).
Got same issues for other wsdl files, but this is the easiest example, to explain.
What is the expected go version?
The .travis.yml file suggests that all test must pass with go 1.6-1.9. However, the package_test.go file uses golang 1.8+ feature (such as test.Name etc.).
Running the tool over the ONVIF specification produces the following error:
2017/12/02 17:44:05 wsdl import: could not open file raw: path: ../../../ver10/schema/onvif.xsd escaped: ../../../ver10/schema/onvif.xsd : open ../../../ver10/schema/onvif.xsd: no such file or directory
Upon closer inspection of the WSDL, it appears it does some relative importing:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../../../ver20/util/onvif-wsdl-viewer.xsl"?>
<!--
Copyright (c) 2008-2017 by ONVIF: Open Network Video Interface Forum. All rights reserved.
Recipients of this document may copy, distribute, publish, or display this document so long as this copyright notice, license and disclaimer are retained with all copies of the document. No license is granted to modify this document.
THIS DOCUMENT IS PROVIDED "AS IS," AND THE CORPORATION AND ITS MEMBERS AND THEIR AFFILIATES, MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THIS DOCUMENT ARE SUITABLE FOR ANY PURPOSE; OR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
IN NO EVENT WILL THE CORPORATION OR ITS MEMBERS OR THEIR AFFILIATES BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THIS DOCUMENT, WHETHER OR NOT (1) THE CORPORATION, MEMBERS OR THEIR AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR (2) SUCH DAMAGES WERE REASONABLY FORESEEABLE, AND ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THIS DOCUMENT. THE FOREGOING DISCLAIMER AND LIMITATION ON LIABILITY DO NOT APPLY TO, INVALIDATE, OR LIMIT REPRESENTATIONS AND WARRANTIES MADE BY THE MEMBERS AND THEIR RESPECTIVE AFFILIATES TO THE CORPORATION AND OTHER MEMBERS IN CERTAIN WRITTEN POLICIES OF THE CORPORATION.
-->
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" targetNamespace="http://www.onvif.org/ver10/device/wsdl">
<wsdl:types>
<xs:schema targetNamespace="http://www.onvif.org/ver10/device/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" elementFormDefault="qualified" version="17.06">
<xs:import namespace="http://www.onvif.org/ver10/schema" schemaLocation="../../../ver10/schema/onvif.xsd"/>
<!--===============================-->
Changes brought in by #75 hardcoded encoder.go such that XMLName is not generated. This should be made configurable.
I try to process this WSDL file (the one from UPS delivery)
https://gist.github.com/vodolaz095/732a0822902b1cb06dd592adbf359e32
I receive this error:
panic: template: interfaceType:10: illegal number syntax: "-"
goroutine 1 [running]:
text/template.Must(0x0, 0x7f15fa332000, 0xc820076e00, 0x0)
/usr/lib/golang/src/text/template/helper.go:23 +0x4b
github.com/fiorix/wsdl2go/wsdlgo.init()
/home/vodolaz095/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:269 +0xe6
main.init()
/home/vodolaz095/go/src/github.com/fiorix/wsdl2go/main.go:87 +0x68
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/lib/golang/src/runtime/asm_amd64.s:1721 +0x1
I use Linux and Go of version go version go1.5.4 linux/amd64
http://www.onvif.org/Documents/Specifications.aspx
ONVIF WSDL and XML Schemas Specifications
...
http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl
...
I have an XML file that has a bunch of types/functions that look like this:
<wsdl:definitions targetNamespace="Namespace">
<wsdl:types>
<xs:schema targetNamespace="Namespace">
<xs:complexType name="ArrayOfString">
<xs:sequence>
<xs:element name="stringItem" type="xs:string" minOccurs="0" maxOccurs="unbounded" nillable="false"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Tag">
<xs:sequence>
<xs:element name="type" type="xs:string" minOccurs="0" maxOccurs="1" nillable="false"/>
<xs:element name="values" type="tns:ArrayOfString" minOccurs="0" maxOccurs="1" nillable="false"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfTag">
<xs:sequence>
<xs:element name="tag" type="tns:Tag" minOccurs="0" maxOccurs="unbounded" nillable="false"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ParamsGetTags">
<xs:sequence>
<xs:element name="tagList" type="tns:ArrayOfTag" minOccurs="0" maxOccurs="1" nillable="false"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ResultGetTags">
<xs:sequence>
<xs:element name="tagList" type="tns:ArrayOfTag" minOccurs="1" maxOccurs="1" nillable="false"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="SuccessGetTags">
<xs:sequence>
<xs:element name="result" type="tns:ResultGetTags" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="paramsGetTags" type="tns:ParamsGetTags"/>
<xs:element name="successGetTags" type="tns:SuccessGetTags"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="GetTagsRequest">
<wsdl:part name="paramsGetTags" element="tns:paramsGetTags"/>
</wsdl:message>
<wsdl:message name="GetTagsResponse">
<wsdl:part name="successGetTags" element="tns:successGetTags"/>
</wsdl:message>
<wsdl:portType name="NPort">
<wsdl:operation name="getTags">
<wsdl:documentation>Get Tags
</wsdl:documentation>
<wsdl:input message="tns:GetTagsRequest"/>
<wsdl:output message="tns:GetTagsResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="NApiSoapBinding" type="tns:NPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getTags">
<soap:operation soapAction="example.com/N/getTags" />
<wsdl:input>
<soap:header use="literal" part="authentication" message="tns:AuthenticationHeader" />
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>
I've included all the definitions (e.g. of ArrayOfTags) for completeness, and since it allows the example above to be complete/testable.
It wasn't working for me, and when I looked more closely, I was able to uncovere the problem. I believe that the line <xs:element name="paramsGetTags" type="tns:ParamsGetTags"/>
should override the "name" on the complex type <xs:complexType name="ParamsGetTags">
. The generated struct is
// ParamsGetTags was auto-generated from WSDL.
type ParamsGetTags struct {
XMLName xml.Name `xml:"Namespace ParamsGetTags" json:"-" yaml:"-"`
TagList *ArrayOfTag `xml:"tagList,omitempty" json:"tagList,omitempty" yaml:"tagList,omitempty"`
}
but it fails when the element name is ParamsGetTags
. If I change it to paramsGetTags
, it works perfectly.
Is there an easy fix you recommend for this? I can dig into some of the code generation, but nothing jumped at me as an easy way to look up if there's another element with that type, and I didn't want to build out a hacky solution if there was something you felt was more appropriate.
Let me know what you think.
Thanks! This library has made my dealing with SOAP in Go much more bearable.
File http://service.businessmall.hp.live.greenova.de/API/1/BusinessmallService.svc?wsdl
// Char was auto-generated from WSDL.
type Char int
// Duration was auto-generated from WSDL.
type Duration Duration // <-- HERE
// Guid was auto-generated from WSDL.
type Guid string
Type defined in http://service.businessmall.hp.live.greenova.de/API/1/BusinessmallService.svc?xsd=xsd1
It compiles, but should be changed.
And maybe a good file for testing, generates about 2000 lines.
Probably a good idea to have some way to automatically generate a mock object that satisfy the interface. This allow easy testing of data that uses the interface.
For example, for the interface Foo
type Foo interface {
CreateMoo(a *CreateMooRequest) (B *CreateMooResponse, err error)
}
We can generate abc_test.go
type MockFoo struct {
Err error
MockCreateMooResponse *CreateMooResponse
}
func (m * MockFoo) CreateMoo(a *CreateMooRequest) (B *CreateMooResponse, err error) {
return m.MockCreateMooResponse, m.Err
}
I have created a working version (using a specific struct, rather than the Message interface used by the generated Client)...
https://play.golang.org/p/9S0Jzk9_C-
and a version that uses the Message interface. Again, this is isolated code from a generated Client.
https://play.golang.org/p/czWZqKEUgG
Has anyone seen the structs being populated correctly when using the Message
interface in Body
?
Using a []byte instead of a Message interface seems to work.
https://play.golang.org/p/qFY2hj5Lnv
If you are happy with this option I would supply a fix. Thoughts?
client.go doesnt send soap action, i change roudtrip function like this (and it works perfectly):
`
// RoundTrip implements the RoundTripper interface.
func (c *Client) RoundTrip(in, out Message) error {
req := &Envelope{
EnvelopeAttr: c.Envelope,
NSAttr: c.Namespace,
Header: c.Header,
Body: Body{Message: in},
}
if req.EnvelopeAttr == "" {
req.EnvelopeAttr = "http://schemas.xmlsoap.org/soap/envelope/"
}
if req.NSAttr == "" {
req.NSAttr = c.URL
}
var b bytes.Buffer
err := xml.NewEncoder(&b).Encode(req)
if err != nil {
return err
}
ct := c.ContentType
if ct == "" {
ct = "text/xml"
}
cli := c.Config
if cli == nil {
cli = http.DefaultClient
}
r, err := http.NewRequest("POST", c.URL, &b)
if err != nil {
return err
}
r.Header.Set("Content-Type", ct)
r.Header.Add("SOAPAction", fmt.Sprintf("%s/%s", c.Namespace, reflect.TypeOf(in).Elem().Name()))
if c.Pre != nil {
c.Pre(r)
}
resp, err := cli.Do(r)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// read only the first Mb of the body in error case
limReader := io.LimitReader(resp.Body, 1024*1024)
body, _ := ioutil.ReadAll(limReader)
return fmt.Errorf("%q: %q", resp.Status, body)
}
return xml.NewDecoder(resp.Body).Decode(out)
}
`
I hope this will be helpfull
Running go vet returns
main.go:98: assignment copies lock value to transport: net/http.Transport contains sync.Mutex
injested wsdl files with - in there field name,
In order to get the program to create the go code,
I needed to go through encoder.go and add string.Replace on '-' with "" one the various tag fields
Found several annoyances while trying to parse this wsdl with @flavioayra:
http://webservices.sabre.com/wsdl/sabreXML1.0.00/usg/SessionCreateRQ.wsdl
Problems include:
Ref: http://webservices.sabre.com/wsdl/sabreXML1.0.00/shopping/msg-header-2_0.xsd
Types we currently can't generate, e.g. PartyId, status.Type, messageStatus.Type.
Hello,
I am trying to use wsdl2go with the WSDL files provided by UK NationalRail as part of OpenLDBWS. When I try this, wsdl2go fails with a stack overflow. Here is what I tried:
curl -o ldbws.wsdl https://lite.realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2017-10-01_ldb.wsdl
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2007-10-10_ldb_common_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2015-11-27_ldb_common_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2017-10-01_ldb_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2016-02-16_ldb_common_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2017-02-02_ldb_common_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2017-10-01_ldb_common_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2012-01-13_ldb_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2015-11-27_ldb_types.xsd
wget https://lite.realtime.nationalrail.co.uk/OpenLDBWS/rtti_2016-02-16_ldb_types.xsd
wsdl2go <ldbws.wsdl >ldbws.go
The result is a very long error message, indicating a stack overflow, which involves the following recursion:
...
github.com/fiorix/wsdl2go/wsdlgo.trimns(0xc42027c560, 0x18, 0x10afc32, 0xc42027c560)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1276 +0x57 fp=0xc440300538 sp=0xc4403004e8 pc=0x12e0f07
github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genComplexContent(0xc42016c2c0, 0x13e32e0, 0xc420145c70, 0xc420162000, 0xc420205b80, 0x2, 0xc4201ee970)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1397 +0x668 fp=0xc440300610 sp=0xc440300538 pc=0x12e2688
github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genStructFields(0xc42016c2c0, 0x13e32e0, 0xc420145c70, 0xc420162000, 0xc420205b80, 0x13a2501, 0x1)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1354 +0x57 fp=0xc440300658 sp=0xc440300610 pc=0x12e1ac7
github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genComplexContent(0xc42016c2c0, 0x13e32e0, 0xc420145c70, 0xc420162000, 0xc420205b80, 0x2, 0xc4201ee970)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1399 +0x6e4 fp=0xc440300730 sp=0xc440300658 pc=0x12e2704
github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genStructFields(0xc42016c2c0, 0x13e32e0, 0xc420145c70, 0xc420162000, 0xc420205b80, 0x13a2501, 0x1)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1354 +0x57 fp=0xc440300778 sp=0xc440300730 pc=0x12e1ac7
github.com/fiorix/wsdl2go/wsdlgo.(*goEncoder).genComplexContent(0xc42016c2c0, 0x13e32e0, 0xc420145c70, 0xc420162000, 0xc420205b80, 0x2, 0xc4201ee970)
/Users/voss/go/src/github.com/fiorix/wsdl2go/wsdlgo/encoder.go:1399 +0x6e4 fp=0xc440300850 sp=0xc440300778 pc=0x12e2704
...
I wonder whether the test if exists {...}
really should be if !exists {...}
?
Line 1398 in 9f9d740
Currently, the name for complex object is generated from the target namespace as specified in WSDL file.
However, in some legacy SOAP system, it is required that the SOAP message body object's namespace be different than the one specified in the wsdl file. Thus, it would be advantageous to allow override of the default (correct) behaviour.
I realized today, that this lib shows odd behavior when using soap funcs which either don't take any parameters, or more than one.
The first one of course is explained by this TODO in-code. However, the if clause at this position also has an oversight which causes wrong method templating on soap funcs with more than one parameter. In this case the parameters end up in the go func definition, but are not passed to p.cli.RoundTripWithAction.
If welcome, I can cook up at least some test cases, and maybe some potential enhancements to fix the issues.
Edit: I see the "more than 1 parameter" issue is tracked by #65
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.