UriEndpointmapping working with attribute setendpointmapping - Spring Integration ws - spring-integration

I am trying to set property setendpointmapping of object UriEndpointmapping with a hashmap with the followings values:
UriEndpointMapping uriEndpointMapping = new UriEndpointMapping();
Map<String,Object> endpointMap = new HashMap<>();
endpointMap.put("/miservicio/cliente", gateway);
endpointMap.put("/miservicio/cliente.wsdl", wsdlDefinition());
uriEndpointMapping.setEndpointMap(endpointMap);
Where: gateway is an bean of type int-ws:inbound-gateway
and wsdlDefinition is a method to return DefaultWsdl11Definition
So, When I call from of browser localhost:8080/miservicio/cliente.wsdl, I don't get a response. Thus, How should I work it?

You misunderstood the UriEndpointMapping logic a bit:
* Implementation of the {#code EndpointMapping} interface to map from the full request URI or request URI path to
* endpoint beans.
The WSDL definition logic is a bit different and it is done like a part of the MessageDispatcherServlet startup logic:
private void initWsdlDefinitions(ApplicationContext context) {
wsdlDefinitions = BeanFactoryUtils
.beansOfTypeIncludingAncestors(context, WsdlDefinition.class, true, false);
The WSDL selection logic from there by the incoming request is like this:
protected WsdlDefinition getWsdlDefinition(HttpServletRequest request) {
if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) &&
request.getRequestURI().endsWith(WSDL_SUFFIX_NAME)) {
String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI());
return wsdlDefinitions.get(fileName);
}
else {
return null;
}
}
And let's take some sample from the Spring WS documentation:
<sws:dynamic-wsdl id="holiday"
portTypeName="HumanResource"
locationUri="/holidayService/"
targetNamespace="http://mycompany.com/hr/definitions">
<sws:xsd location="/WEB-INF/hr.xsd"/>
</sws:dynamic-wsdl>
and this quote:
The id determines the URL where the WSDL can be retrieved. In this case, the id is holiday, which means that the WSDL can be retrieved as holiday.wsdl in the servlet context. The full URL will typically be http://localhost:8080/holidayService/holiday.wsdl

Related

Invoking Xtext Generator via Language Server Protocol explicitly

I have a DSL project using Xtext together with the Language Server Protocol.
Now I want to trigger a Generator from the client (in my case VS Code) to be executed on the server.
Not automatically (I would know how to do that), but explicitly triggered by the user from a VS Code command.
I am aware of the IExecutableCommandService in Xtext and I know how to hook into it.
But I don't know how to retrieve the corresponding Resource from a given file path:
#Override
public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, CancelIndicator cancelIndicator) {
if ("c4.generator.type".equals(params.getCommand())) {
// fileURI passed from client to the server
String fileURI = ((JsonPrimitive)params.getArguments().get(0)).getAsString();
// This is where I stuck
Resource resource = whatAPItoCallToRetrieveResourceFromFile(fileURI);
// Call the generator then
doGenerate(resource);
}
return "Unknown Command";
}
The use-case is the same as described in this blog: https://dietrich-it.de/xtext/2011/10/15/xtext-calling-the-generator-from-a-context-menu/
But the description is for Eclipse only (not using lsp).
If you already have the correct URI, you should be able to use XtextResourceSet to get access to the resource:
final XtextResourceSet rs = new XtextResourceSet();
final Resource r = rs.getResource(fileURI, true);
doGenerate(r);
otherwise you can get access to the Xtext index and iterate over all resources searching for the resource of interest, by using access.doReadIndex:
final XtextResourceSet rs = new XtextResourceSet();
final Function<ILanguageServerAccess.IndexContext, Boolean> func = (
ILanguageServerAccess.IndexContext ctxt) -> {
for (final IResourceDescription rd: ctxt.getIndex().getAllResourceDescriptions()) {
if(<check_rd>) {
Resource r = rs.getResource(rd.getURI(), true);
doGenerate(r);
}
}
return true;
};
access.doReadIndex(func);

Rest Assured with Cucumber: How to put the request information inside the HTML report

I would like to show my requests and responses details in my HTML report.
A feature file example:
Feature: Rest Assured under Cucumber POC
Scenario: Azure Login Scenario
Given Request specifications are set with base uri "https://login.microsoftonline.com/"
When Azure Login Request Executed
Then Verify Status Code is 200
The Runner class is:
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/main/resources/features",
glue = {""},
tags = "#tests",
plugin = { "pretty",
"json:target/cucumber-reports/Cucumber.json",
"html:target/cucumber-reports"}//reporting plugin
)
public class CucumberRunner {}
The steps are:
#Given("Request specifications are set with base uri {string}")
public void setRequestsSpec(String baseUri){
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri(baseUri)
.addFilter(new ResponseLoggingFilter())//log request and response for better debugging. You can also only log if a requests fails.
.addFilter(new RequestLoggingFilter())
.build();
testContext().setRequestSpec(spec);
}
#When("^Azure Login Request Executed$")
public void azureLoginExecuted() {
response =
given() //Add x-www-form-urlencoded body params:
.formParam(GRANT_TYPE_KEY, GRANT_TYPE_VALUE)
.formParam(AUTO_TEAM_CLIENT_ID_KEY, AUTO_TEAM_CLIENT_ID_VALUE)
.formParam(AUTO_TEAM_CLIENT_SECRET_KEY, AUTO_TEAM_CLIENT_SECRET_VALUE)
.formParam(RESOURCE_KEY, RESOURCE_VALUE)
.when()
.post(AUTO_TEAM_TENANT_ID + RESOURCE); //Send the request along with the resource
testContext().setResponse(response);
setAuthorizationToken();
}
#Then("Verify Status Code is {int}")
public void verifyStatusCode(int expected_repsonse_code) {
testContext().getResponse().then().statusCode(expected_repsonse_code);
}
Currently I found out how to show those details only in my IntelliJ console:
For example:
#tests
Feature: Rest Assured under Cucumber POC
#tests
Scenario: Azure Login Scenario # src/main/resources/features/poc.feature:5
Given Request specifications are set with base uri "https://login.microsoftonline.com/" # CommonStepsDefinitions.setRequestsSpec(String)
Request method: POST
Request URI: https://login.microsoftonline.com/6ae4e000-b5d0-4f48-a766-402d46119b76/oauth2/token
Proxy: <none>
Request params: <none>
Query params: <none>
and more..
But the HTML report shows only:
Thank you!
You can log the RestAssured output to your cucumber scenario report by just setting up your RequestSpecification filters in this way:
ByteArrayOutputStream requestResponseBuffer = new ByteArrayOutputStream();
PrintStream requestResponsePrintStream = new PrintStream(requestResponseBuffer , true);
List<Filter> loggingFilters = Arrays.asList(
new RequestLoggingFilter(requestResponsePrintStream),
new CucumberReportLoggingFilter(requestResponseBuffer, scenario),
new ResponseLoggingFilter(requestResponsePrintStream)
);
RequestSpecification requestSpecification = RestAssured.given()
.filters(loggingFilters)
:
where the CucumberReportLoggingFilter class looks like this:
class CucumberReportLoggingFilter implements Filter {
ByteArrayOutputStream requestResponseBuffer;
Scenario scenario;
CucumberReportLoggingFilter(ByteArrayOutputStream requestResponseBuffer, Scenario scenario) {
this.requestResponseBuffer = requestResponseBuffer;
this.scenario = scenario;
}
#Override
Response filter(FilterableRequestSpecification requestSpec,
FilterableResponseSpecification responseSpec, FilterContext ctx) {
// Call the next filter(s) which logs the response to the requestResponseBuffer
Response response = ctx.next(requestSpec, responseSpec);
scenario.write(requestResponseBuffer.toString());
return response;
}
}
This solution sandwiches the custom CucumberReportLoggingFilter between the standard RequestLoggingFilter and ResponseLoggingFilter filters.
The sequence of filter events that occur when the RequestSpecification sends a Request is:
The standard RequestLoggingFilter filter() method runs and pretty prints the Request details to the requestResponseBuffer.
The custom CucumberReportLoggingFilter filter() method runs and calls the next filter (which is the standard ResponseLoggingFilter filter).
The standard ResponseLoggingFilter filter() method runs and pretty prints the Response details to the requestResponseBuffer.
Control is returned to the custom CucumberReportLoggingFilter filter() method which sends the contents of the requestResponseBuffer to the cucumber report using the scenario.write() method.
Only write out the messages if the scenario fails
You could modify the above solution as follows:
Remove the CucumberReportLoggingFilter.
Make the requestResponseBuffer variable 'scenario-scoped' (i.e. only have one buffer per scenario).
Have the last #After hook that runs in your stepdefs code check the scenario result and if it is failure, write out the contents of the requestResponseBuffer to the cucumber report.
I can give you some details which might not answer your question fully.
In order to add data to Cucumber HTML report you can use:
#After
public void addDataToReport(Scenario scenario) { //scenario is provided from Cucumber
scenario.write(string with the information about scenario);
}
It won't be formatted and I don't know how to change how the report displays it. Each of the messages will be under each Test Case.
You have to, somehow, pass the information to #After hook.
I hope someone else will answer with more details.
EDIT:
In order to store the info about what Scenario is running at the moment, or even in parallel, we can create a class to store necessary information, based on the Thread, so it will be Thread-safe.
Let's create a class to store Scenario. Let's call it Storage
public class Storage {
private static final HashMap<Thread, Scenario> map = new HashMap<>();
public static void putScenario(Scenario scenario) {
map.put(Thread.currentThread(), scenario);
}
public static Scenario getScenario() {
return map.get(Thread.currentThread());
}
}
Now, we have to somehow get the Scenario. It can be achieved by using #Before hook like this:
public class BeforeHook {
#Before(order = 1)
public void getScenario(Scenario scenario) {
Storage.putScenario(scenario);
}
}
#Before hooks are run before each scenario. We get the information about Scenario and put it in Storage so we know what Scenario is run on what Thread.
Remember that hooks have to be reachable by the glue parameter in Cucumber Runner!
And now, if we want to write additional information to the report:
#Then("Data is saved to the report")
public void data_is_saved_to_the_report() {
System.out.println("Saving data to report");
Storage.getScenario().write("Test data and stuff");
}
We just get current scenario from the Storage and use Scenario.write() method to add information to the report.
It will look like this in the report:

struggling with an ASP.NET MVC5 routing issue

So, I have an MVC5 site that uses the default routing template {controller}/{action}/{id} and this works fine. Most everything in the site requires a login (i.e. [Authorize] attribute is used almost everywhere), and this works fine.
Well, now I have a need to allow anonymous access to select pages when a certain kind of link pattern is used: App/{token}/{action}. The {token} is a random string associated with something in my database. I can issue and deactivate these tokens at will.
I got this new App/{token}/{action} routing working by implementing a custom RouteBase that parses the incoming URL for these tokens, and, crucially, adds the the token value to the RouteData.DataTokens so that my App controller can make use of it without needing an explicit action argument for it. So, I added this new route to the route table ahead of the default routing like this:
// new route here
routes.Add("AppToken", new AnonAppAccessRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Here is the problem/question: adding this now route has now made my default route stop working -- everything is now going through AnonAppAccessRoute which of course is meant to work only for a few things. I don't understand how to make my AnonAppAccessRoute apply only to URLs with a certain pattern. The MapRoute method accepts a URL pattern, but Adding a route doesn't seem to let you put a filter on it. What am I missing? I've looked around quite a bit at various blogs and documentation about routing, but I've not found good info about using the DataTokens collection (which I feel is important to my approach), and I'm not seeing a good explanation of the difference between Adding a route explicitly vs calling MapRoute.
Here's the code of my custom RouteBase:
public class AnonAppAccessRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string[] pathElements = httpContext.Request.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (pathElements.Length > 0)
{
string token = TryGetArrayElement(pathElements, 1);
if (!string.IsNullOrEmpty(token))
{
result = new RouteData(this, new MvcRouteHandler());
result.DataTokens.Add("appToken", token);
result.Values.Add("controller", "App");
result.Values.Add("action", TryGetArrayElement(pathElements, 2, "Index"));
}
}
return result;
}
private string TryGetArrayElement(string[] array, int index, string defaultValue = null)
{
try
{
return array[index];
}
catch
{
return defaultValue;
}
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
I got this to work by dropping the custom RouteBase and instead used this MapRoute call like this:
routes.MapRoute(
name: "AppAnon",
url: "App/{token}/{action}",
defaults: new { controller = "App", action = "Index" }
);
Then, in my App controller, I did this in the Initialize override:
protected AppToken _appToken = null;
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
string token = requestContext.RouteData.Values["token"]?.ToString();
_appToken = Db.FindWhere<AppToken>("[Token]=#token", new { token });
if (!_appToken?.IsActive ?? false) throw new Exception("The token is not found or inactive.");
}
This way, my "token" is available to all controller actions via the _appToken variable, and already validated. I did not need to use RouteData.DataTokens. Note that my Db.FindWhere statement is ORM-specific and not really related to the question -- it's just how I look up a database record.

SQLInjection against CosmosDB in an Azure function

I have implemented an Azure function that is triggered by a HttpRequest. A parameter called name is passed as part of the HttpRequest. In Integration section, I have used the following query to retrieve data from CosmosDB (as an input):
SELECT * FROM c.my_collection pm
WHERE
Contains(pm.first_name,{name})
As you see I am sending the 'name' without sanitizing it. Is there any SQLInjection concern here?
I searched and noticed that parameterization is available but that is not something I can do anything about here.
When the binding occurs (the data from the HTTP Trigger gets sent to the Cosmos DB Input bind), it is passed through a SQLParameterCollection that will handle sanitization.
Please view this article:
Parameterized SQL provides robust handling and escaping of user input, preventing accidental exposure of data through “SQL injection”
This will cover any attempt to inject SQL through the name property.
If you're using Microsoft.Azure.Cosmos instead of Microsoft.Azure.Documents:
public class MyContainerDbService : IMyContainerDbService
{
private Container _container;
public MyContainerDbService(CosmosClient dbClient)
{
this._container = dbClient.GetContainer("MyDatabaseId", "MyContainerId");
}
public async Task<IEnumerable<MyEntry>> GetMyEntriesAsync(string queryString, Dictionary<string, object> parameters)
{
if ((parameters?.Count ?? 0) < 1)
{
throw new ArgumentException("Parameters are required to prevent SQL injection.");
}
var queryDef = new QueryDefinition(queryString);
foreach(var parm in parameters)
{
queryDef.WithParameter(parm.Key, parm.Value);
}
var query = this._container.GetItemQueryIterator<MyEntry>(queryDef);
List<MyEntry> results = new List<MyEntry>();
while (query.HasMoreResults)
{
var response = await query.ReadNextAsync();
results.AddRange(response.ToList());
}
return results;
}
}

Get a content edit URL as a string without UrlHelpers or Orchard tokens

I'm trying to get the edit URL of a content as a string from backend, the catch is I'm inside a workflow activity, so I can't use Url.Action... or Url.ItemEditLink... or other UrlHelpers as if it were a controller or a view. Also, although I'm inside a workflow, the contents I need it for are not part of the workflowContext or the activityContext, so I can't use those or tokens either.
A solution could be to get the content metadata and the site baseUrl and try to build it manually, but I think this way is prone to errors.
Thanks.
This is how I build a Uri in an activity:
public class MyClass : Task
{
private readonly RequestContext _requestContext;
...
public MyActivity(RequestContext requestContext, ...)
{
_requestContext = requestContext;
...
}
...
public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext)
{
var content = ... get using ID
var helper = new UrlHelper(_requestContext);
var baseurl = new Uri(_orchardServices.WorkContext.CurrentSite.BaseUrl);
Uri completeurl = new Uri(baseurl, helper.ItemDisplayUrl(content));
yield return T("Done");
}
}
Turns out that I actually do build the Uri semi-manually, but I haven't had issues with this method. You may be able to use just the ItemDisplayUrl for navigation inside of Orchard; I had to get the full URL because the string gets sent to an outside program (Slack).

Resources