Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(soap): add SOAPAction header #8282

Merged
merged 5 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/sour-carrots-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@graphql-mesh/transport-soap': patch
'@omnigraph/soap': patch
---

Some SOAP API endpoints need `SOAPAction` HTTP header that points to the action path defined in the
WSDL.
This fixes that issue for those endpoints.
[Learn more about SOAPAction header](https://www.ibm.com/docs/en/baw/22.x?topic=binding-protocol-headers)
1 change: 1 addition & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
YARN_ENABLE_HARDENED_MODE: 0
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ env:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
deployment:
Expand Down
10 changes: 10 additions & 0 deletions e2e/soap-demo/__snapshots__/soap-demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ directive @soap(
subgraph: String
bodyAlias: String
soapHeaders: SOAPHeaders
soapAction: String
) repeatable on FIELD_DEFINITION
directive @extraSchemaDefinitionDirective(directives: _DirectiveExtensions) repeatable on OBJECT
Expand Down Expand Up @@ -120,30 +121,35 @@ type Query @extraSchemaDefinitionDirective(directives: {transport: [{kind: "soap
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.FindPerson"
)
s0_SOAPDemo_SOAPDemoSoap_GetByName(GetByName: s0_GetByName_Input = {}) : s0_GetByNameResponse @soap(
elementName: "GetByNameResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.GetByName"
)
s0_SOAPDemo_SOAPDemoSoap_GetDataSetByName(GetDataSetByName: s0_GetDataSetByName_Input = {}) : s0_GetDataSetByNameResponse @soap(
elementName: "GetDataSetByNameResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.GetDataSetByName"
)
s0_SOAPDemo_SOAPDemoSoap_GetListByName(GetListByName: s0_GetListByName_Input = {}) : s0_GetListByNameResponse @soap(
elementName: "GetListByNameResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.GetListByName"
)
s0_SOAPDemo_SOAPDemoSoap_QueryByName(QueryByName: s0_QueryByName_Input = {}) : s0_QueryByNameResponse @soap(
elementName: "QueryByNameResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.QueryByName"
)
}
Expand Down Expand Up @@ -228,24 +234,28 @@ type Mutation @join__type(graph: SOAP_DEMO) {
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.AddInteger"
)
s0_SOAPDemo_SOAPDemoSoap_DivideInteger(DivideInteger: s0_DivideInteger_Input = {}) : s0_DivideIntegerResponse @soap(
elementName: "DivideIntegerResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.DivideInteger"
)
s0_SOAPDemo_SOAPDemoSoap_LookupCity(LookupCity: s0_LookupCity_Input = {}) : s0_LookupCityResponse @soap(
elementName: "LookupCityResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.LookupCity"
)
s0_SOAPDemo_SOAPDemoSoap_Mission(Mission: JSON = "") : s0_MissionResponse @soap(
elementName: "MissionResponse"
bindingNamespace: "http://tempuri.org"
endpoint: "http://localhost:<soap-demo_port>/csp/samples/SOAP.Demo.cls"
subgraph: "soap-demo"
soapAction: "http://tempuri.org/SOAP.Demo.Mission"
)
}
Expand Down
1 change: 0 additions & 1 deletion examples/soap-demo/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ sources:
handler:
soap:
source: https://www.crcind.com/csp/samples/SOAP.Demo.cls?WSDL
selectQueryOperationsAuto: true

documents:
- ./operations/*.graphql
250 changes: 250 additions & 0 deletions examples/soap-demo/tests/__snapshots__/soap-demo.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SOAP Demo should generate correct schema: soap-demo-schema 1`] = `
"schema @transport(kind: "soap", subgraph: "SOAPDemo") {
query: Query
mutation: Mutation
}
directive @soap(bindingNamespace: String, bodyAlias: String, elementName: String, endpoint: String, soapAction: String, soapHeaders: SOAPHeaders, subgraph: String) on FIELD_DEFINITION
"""
The \`BigInt\` scalar type represents non-fractional signed whole numeric values.
"""
scalar BigInt
type ByNameDataSet_ByName {
DOB: Date
ID: BigInt
Name: String
SSN: String
}
"""
A date string, such as 2007-12-03, compliant with the \`full-date\` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
"""
scalar Date
"""
The \`JSON\` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSON
type Mutation {
s0_SOAPDemo_SOAPDemoSoap_AddInteger(AddInteger: s0_AddInteger_Input = {}): s0_AddIntegerResponse @soap(elementName: "AddIntegerResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.AddInteger")
s0_SOAPDemo_SOAPDemoSoap_DivideInteger(DivideInteger: s0_DivideInteger_Input = {}): s0_DivideIntegerResponse @soap(elementName: "DivideIntegerResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.DivideInteger")
s0_SOAPDemo_SOAPDemoSoap_LookupCity(LookupCity: s0_LookupCity_Input = {}): s0_LookupCityResponse @soap(elementName: "LookupCityResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.LookupCity")
s0_SOAPDemo_SOAPDemoSoap_Mission(Mission: JSON = ""): s0_MissionResponse @soap(elementName: "MissionResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.Mission")
}
scalar ObjMap
type Query {
s0_SOAPDemo_SOAPDemoSoap_FindPerson(FindPerson: s0_FindPerson_Input = {}): s0_FindPersonResponse @soap(elementName: "FindPersonResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.FindPerson")
s0_SOAPDemo_SOAPDemoSoap_GetByName(GetByName: s0_GetByName_Input = {}): s0_GetByNameResponse @soap(elementName: "GetByNameResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.GetByName")
s0_SOAPDemo_SOAPDemoSoap_GetDataSetByName(GetDataSetByName: s0_GetDataSetByName_Input = {}): s0_GetDataSetByNameResponse @soap(elementName: "GetDataSetByNameResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.GetDataSetByName")
s0_SOAPDemo_SOAPDemoSoap_GetListByName(GetListByName: s0_GetListByName_Input = {}): s0_GetListByNameResponse @soap(elementName: "GetListByNameResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.GetListByName")
s0_SOAPDemo_SOAPDemoSoap_QueryByName(QueryByName: s0_QueryByName_Input = {}): s0_QueryByNameResponse @soap(elementName: "QueryByNameResponse", bindingNamespace: "http://tempuri.org", endpoint: "https://www.crcind.com:443/csp/samples/SOAP.Demo.cls", subgraph: "SOAPDemo", soapAction: "http://tempuri.org/SOAP.Demo.QueryByName")
}
type QueryByName_DataSet_QueryByName {
DOB: Date
ID: BigInt
Name: String
SSN: String
}
input SOAPHeaders {
alias: String
headers: ObjMap
namespace: String
}
type s0_AddIntegerResponse {
AddIntegerResult: BigInt
}
input s0_AddInteger_Input {
Arg1: BigInt
Arg2: BigInt
}
type s0_Address {
City: String
State: String
Street: String
Zip: String
}
type s0_ArrayOfFavoriteColorsItemString {
FavoriteColorsItem: [String]
}
type s0_ArrayOfPersonIdentificationPersonIdentification {
PersonIdentification: [s0_PersonIdentification]
}
type s0_ByNameDataSet {
ByName: [ByNameDataSet_ByName]
}
type s0_DivideIntegerResponse {
DivideIntegerResult: BigInt
}
input s0_DivideInteger_Input {
Arg1: BigInt
Arg2: BigInt
}
type s0_FindPersonResponse {
FindPersonResult: s0_Person
}
input s0_FindPerson_Input {
id: String
}
type s0_GetByNameResponse {
GetByNameResult: JSON
}
input s0_GetByName_Input {
name: String
}
type s0_GetDataSetByNameResponse {
GetDataSetByNameResult: s0_ByNameDataSet
}
input s0_GetDataSetByName_Input {
name: String
}
type s0_GetListByNameResponse {
GetListByNameResult: s0_ArrayOfPersonIdentificationPersonIdentification
}
input s0_GetListByName_Input {
name: String
}
type s0_LookupCityResponse {
LookupCityResult: s0_Address
}
input s0_LookupCity_Input {
zip: String
}
type s0_MissionResponse {
MissionResult: String
}
type s0_Person {
Age: BigInt
DOB: Date
FavoriteColors: s0_ArrayOfFavoriteColorsItemString
Home: s0_Address
Name: String
Office: s0_Address
SSN: String
Spouse: s0_Person
}
type s0_PersonIdentification {
DOB: Date
ID: String
Name: String
SSN: String
}
type s0_QueryByNameResponse {
QueryByNameResult: s0_QueryByName_DataSet
}
type s0_QueryByName_DataSet {
QueryByName: [QueryByName_DataSet_QueryByName]
}
input s0_QueryByName_Input {
name: String
}"
`;

exports[`SOAP Demo should give correct response for example queries: AddInteger.graphql-soap-demo-result 1`] = `
{
"data": {
"s0_SOAPDemo_SOAPDemoSoap_AddInteger": {
"AddIntegerResult": 5,
},
},
}
`;

exports[`SOAP Demo should give correct response for example queries: DivideInteger.graphql-soap-demo-result 1`] = `
{
"data": {
"s0_SOAPDemo_SOAPDemoSoap_DivideInteger": {
"DivideIntegerResult": 5,
},
},
}
`;

exports[`SOAP Demo should give correct response for example queries: FindPerson.graphql-soap-demo-result 1`] = `
{
"data": {
"s0_SOAPDemo_SOAPDemoSoap_FindPerson": {
"FindPersonResult": {
"Age": 24,
"DOB": "2000-03-20",
"FavoriteColors": {
"FavoriteColorsItem": [
"Red",
],
},
"Home": {
"City": "Pueblo",
"State": "AK",
"Street": "6977 First Street",
"Zip": "63163",
},
"Name": "Newton,Dave R.",
"Office": {
"City": "Washington",
"State": "MN",
"Street": "9984 Second Blvd",
"Zip": "42829",
},
"SSN": "384-10-6538",
},
},
},
}
`;

exports[`SOAP Demo should give correct response for example queries: GetListByName.graphql-soap-demo-result 1`] = `
{
"data": {
"s0_SOAPDemo_SOAPDemoSoap_GetListByName": {
"GetListByNameResult": {
"PersonIdentification": [
{
"DOB": "2000-03-20",
"ID": "1",
"Name": "Newton,Dave R.",
"SSN": "384-10-6538",
},
{
"DOB": "2004-11-17",
"ID": "29",
"Name": "Newton,Mario B.",
"SSN": "538-68-5047",
},
],
},
},
},
}
`;
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
const { findAndParseConfig } = require('@graphql-mesh/cli');
const { getMesh } = require('@graphql-mesh/runtime');
const { basename, join } = require('path');

const { lexicographicSortSchema } = require('graphql');
const { MeshStore, InMemoryStoreStorageAdapter } = require('@graphql-mesh/store');
const { printSchemaWithDirectives } = require('@graphql-tools/utils');
import { basename, join } from 'path';
import { lexicographicSortSchema } from 'graphql';
import { findAndParseConfig } from '@graphql-mesh/cli';
import { getMesh } from '@graphql-mesh/runtime';
import { InMemoryStoreStorageAdapter, MeshStore } from '@graphql-mesh/store';
import { printSchemaWithDirectives } from '@graphql-tools/utils';

const store = new MeshStore('soap', new InMemoryStoreStorageAdapter(), {
readonly: false,
Expand All @@ -21,13 +20,16 @@ jest.setTimeout(30000);
describe('SOAP Demo', () => {
it('should generate correct schema', async () => {
const { schema } = await mesh$;
expect(printSchemaWithDirectives(lexicographicSortSchema(schema))).toMatchSnapshot('soap-demo-schema');
expect(printSchemaWithDirectives(lexicographicSortSchema(schema))).toMatchSnapshot(
'soap-demo-schema',
);
});
it('should give correct response for example queries', async () => {
const { documents } = await config$;
const { execute } = await mesh$;
for (const source of documents) {
const result = await execute(source.document);
expect(result.errors).toBeUndefined();
expect(result).toMatchSnapshot(basename(source.location) + '-soap-demo-result');
}
});
Expand Down
Loading
Loading