Repository navigation
Add SoapCore.UI: a Swagger-like explorer for SoapCore services - #1199
Open
frankyjquintero wants to merge 2 commits into
Open
frankyjquintero wants to merge 2 commits into
frankyjquintero wants to merge 2 commits into
Conversation
Permite el listado programático de los servicios SOAP configurados con UseSoapEndpoint. Resuelve la limitación de que EndpointDataSource de ASP.NET Core no expone detalles suficientes para los servicios SoapCore. Esto facilita la creación de catálogos de servicios, gateways y herramientas de observabilidad. La funcionalidad es opt-in, thread-safe y registra un snapshot de la configuración del endpoint.
Este nuevo paquete proporciona una interfaz gráfica similar a Swagger que permite descubrir, documentar y probar endpoints SOAP configurados con SoapCore. Utiliza `ISoapEndpointRegistry` para listar los servicios, generar envolventes SOAP de ejemplo a partir del WSDL y enviar solicitudes directamente desde el navegador. Mejora la experiencia del desarrollador y facilita la depuración de servicios. Incluye un nuevo proyecto de ejemplo (`ServerWithUi`) y pruebas exhaustivas. Requiere SoapCore 1.2.1.17 o posterior para funcionar.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add SoapCore.UI: a Swagger-like explorer for SoapCore services
Summary
SoapCore.UIis a new, separate NuGet package that adds one page to an ASP.NET Core application: a Swagger-UI-like explorer for the SOAP endpoints SoapCore hosts. It lists the endpoints, shows their operations and documentation, generates a sample SOAP envelope from the endpoint's WSDL and lets you call the endpoint from the browser ("Try it out").It is built on the registry from #1190: nothing is guessed from the route table, and endpoints registered in middleware mode are listed too.
It has no server-side proxy, makes no external request (no CDN, fonts or analytics) and has no npm or build step: the front end is plain JavaScript and CSS embedded in the assembly.
Why a separate package
SoapCorepackage keeps its dependencies and target frameworks.SoapCore.UItargetsnet8.0only and depends onSoapCore.MapSoapCoreUi().What it does
Finds and documents the services
ISoapEndpointRegistry(routing and middleware mode), grouped by contract, with badges for the SOAP versions and the serializer.ExposeOperationDetailsit also shows parameters (in/out/ref), the return type, declared faults and message-contract flags.[Description]and from XML documentation files (IncludeXmlComments).dotnet-svcutilcommand.Lets you try an operation
nil). The XML is always the source of truth: the form is rebuilt from it whenever you switch to it.AddSoapWsSecurityFiltervalidates). Credentials stay in memory.HttpClientor raw HTTP. Secrets are shown asREDACTED.How to try it (demo credentials)
Open http://localhost:5290/soap-ui. The
httplaunch profile setsASPNETCORE_ENVIRONMENT=Development, which is what turns the explorer on in the sample./Secure.svcanswers only callers that authenticate (anything else gets HTTP 401 and a SOAP fault) and accepts any one of these four schemes. Press Authorize in the explorer, pick a scheme, type the value and sendWhoAmI, which tells you which scheme was used:Authorization: Bearer <token>demo-tokenAuthorization: Basic <base64 of user:password>demodemo-passwordX-Api-Key(the name isSoapUiOptions.ApiKeyHeaderName)X-Api-Keydemo-keywsse:SecuritySOAP header, with the password as text or as a digestdemodemo-passwordOther things to try:
/NoWsdl.svc→EchoWithTokenX-Demo-Token: demo/Weather.svc→GetReport,GetForecast,GetDailyForecast,GetCurrentCondition,CityExistsstring, which is not a city, soGetReportandGetDailyForecastanswer with a SOAP fault. Replace itBOG,MDE,NYCorLON/Weather.svc→GetReportorGetDailyForecastWeatherFault, which the explorer shows as a SOAP fault. (GetForecastreturns an empty list andGetCurrentConditionanswersCloudyfor an unknown city.)ZZZ/Service.asmx→PingComplexModelDateTimeOffsetand an enumCommand-line check of
/Secure.svc(bash):The sample README has the WS-Security envelopes (plain text and a worked digest). The explorer builds them for you when you choose that scheme.
Security model
This is a development and diagnostics tool. The package README has the full model; the main points:
Hostheader; it was removed.)MapSoapCoreUi()returns anIEndpointConventionBuilder(a route group): chain.RequireAuthorization(),.RequireHost()or.RequireCors(). The UI logs a warning when it is served without authorization outside Development.Content-Security-Policy(default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; ...),X-Content-Type-Options,Referrer-Policy,X-Frame-Options,Cache-Control.Originis answered with 403 even if the host has a permissive CORS policy. The README explains why this does not stop DNS rebinding (AllowedHosts,RequireHost).innerHTMLfamily,eval, inline script/style or external URLs. Everything coming from a WSDL or a response is written withtextContent, and everything inserted into generated XML is escaped. C# tests scan the embedded files for these constructs.ExposeOperationDetails(CLR type names) is off by default.SendTimeoutSecondsandMaxResponseBytesare limits of the page, not protections of the server, and the README says so.Changes outside the new projects
src/SoapCore.sln,samples/Sample.slnsrc/SoapCore.Tests/SoapCore.Tests.csprojProjectReferencetoSoapCore.UI, and theJintpackage (see "Tests").github/workflows/publish.ymlSoapCore.UIafterSoapCore. A UI failure cannot block the core release, and--skip-duplicateapplies to the UI package onlyREADME.mdsrc/SoapCore/**is not touched by this PR.What is new
src/SoapCore.UIAddSoapCoreUi,MapSoapCoreUi, the catalog built from the registry (cachedServiceDescription, descriptions provider), the asset whitelist, andEmbeddedUI/(HTML, 4 JS files, 2 CSS files)samples/ServerWithUi/Secure.svc, which accepts a bearer token, Basic, an API key or a WS-Security UsernameToken to try the Authorize panel (public demo credentials)src/SoapCore.Tests/UiRough size: about 3,000 lines of C#, 10,000 of JavaScript and 2,900 of CSS/HTML in the package; the tests are larger than the code.
Tests
dotnet test src/SoapCore.Testspasses (2,666 tests in the project, about 2,350 of them new).TestServer): catalog JSON in both hosting modes, ids for duplicate paths,PathBaseandEndpointPathPrefix, option validation, descriptions and XML comments (including malformed files and DTDs), operation details and their opt-in, asset serving (headers, ETag/304,HEAD,405, path traversal), the cross-origin 403, authorization chaining, and the absence of any proxy route.wsdl-parser.js(escaping, validators, XSD value validation with real ranges, code-snippet builders with hostile inputs, WS-Security digest, XML tokenizer, search, form template, WSDL outline) are executed inside the Jint interpreter, so the existingdotnet testjob runs them without Node. The two functions that need a DOM run against a small XML parser shim included in the test file, which was checked against real Chromium on 11 WSDLs.Verification beyond the automated tests
/Secure.svc; code snippets leak none of the typed secrets in any of the four formats.dotnet-svcutilgenerates a client from the WSDL of every sample endpoint.SoapCore.UIbuilds with no warnings (StyleCop and analyzers are on and warnings are errors in the project).Things you should know before merging
SoapCore.UIneeds the registry, which is not in the publishedSoapCore1.2.1.16.dotnet pack src/SoapCore.UIfails on purpose (a guard in the csproj) untilsrc/SoapCore/SoapCore.csprojhas a<Version>of 1.2.1.17 or later, so a package with an unsatisfiable dependency cannot be pushed by mistake.AddSoapCoreUialso throws a clear error at run time against an older SoapCore. Bumping the version is left to the maintainers.publish.ymlmust be allowed to push the newSoapCore.UIpackage id.javascriptshould be added to the languages ofcodeql-analysis.yml. I did not change that workflow.net8.0only, which is the newest SDK the CI installs. Nothing in it needs a newer one.form-editor.jsand its CSS are self-contained and can be dropped behind the existingEnableFormEditoroption), (b) the sample, (c) the front-end tests. I can split it on request.Limitations (documented in the package README)
app.Map(...)andUsePathBase(...)prefixes are not in the registry.EndpointPathPrefixcovers them with one prefix for all endpoints.HttpGetEnabledis needed to show the WSDL. Without it the explorer builds the sample from the operation details (withExposeOperationDetails) or from a generic envelope.MessageVersion.Noneendpoints are listed but cannot be called. File-based WSDL imports are not followed.xs:choiceexclusivity orxs:any(shown read-only, edited in the XML view) and cannot represent mixed content. Requests over 256 KB are shown without syntax highlighting.SoapCore issues found while building this (not changed here)
These live in the library, outside the scope of this PR, and probably deserve their own issues:
DataContractSerializer, an endpoint with both a SOAP 1.1 and a SOAP 1.2 encoder and noBindingName/PortNamegets the same name for both bindings and both ports in its WSDL (MetaWCFBodyWriter.GetSoapMetaParameters; theXmlSerializerwriter adds a_soap/_soap12suffix).dotnet-svcutilthen fails withMore than one binding named .... The sample works around it by naming the SOAP 1.2 encoder.DateTimeOffsetandGuidasxsd:string. WithXmlSerializerthe WSDL says nothing about the real type. The explorer guesses aDateTimeOffsetby element name.urn:DataContract namespaces. The schema namespace is prefixed withhttp://schemas.datacontract.org/2004/07/but the type references are not, so the WSDL is inconsistent.ProcessHttpOperation(GET/POST {path}/{Operation}, enabled byHttpGetEnabled/HttpPostEnabled) does not go throughISoapMessageProcessor,IAsyncMessageFilterorIMessageInspector2. Anyone who protects an endpoint with one of those can be bypassed through that route. I found this by reading the middleware and by the sample's/Secure.svc, which needs a small guard for it; I did not try to exploit it beyond that.Questions for the maintainers
net8.0only acceptable, and is a0.1.0-preview.1version with its own release step the right way to ship it?Checklist
SoapCorealone, andsrc/SoapCoreis untouchedSoapCoreversion bump (maintainers)publish.ymland CodeQL changes reviewed (maintainers)