how call REST service with path variable in webmethod? - rest

I'm using WM9.8. I want to know how to call a GET REST service with path variable like:
http://localhost:8080/client/1 in webmethod.
I can call POST rest service using pub.client.http. But it dosen't work to GET.

Use String varible called "method" to set type of Http request method.

Just put the path variable in the URL and made a substitution to the path variable
e.g: http://localhost:8080/client/%yourPathVariableHere%

Holy cow this is an old question but I just tumbled across it and I thought I might helps somebody else who does.
URLs in webmethods are fixed to a single value, like /client unless you enable watt.server.url.alias.partialMatching=true
After that, you can simply alias a service to /client and all subURLs like /client/1 are sent to that service. You still have to parse them to get the ID out.
Be careful, though, because ALL sub URLs are sent to the service. So after enabling this flag I get /client, /client/1, /client/1/name all going to the same service. You can see how this can quickly become REST-unfriendly.

Related

Apache ManifoldCF: Get a history report for a repository connection over REST API

I'm trying to get a history report for a repository connection over ManifoldCF REST API. According to the documentation:
https://manifoldcf.apache.org/release/release-2.11/en_US/programmatic-operation.html#History+query+parameters
It should be possible with the following URL (connection name: myConnection):
http://localhost:8345/mcf-api-service/json/repositoryconnectionhistory/myConnection
I have also tried to use some of the history query parameters:
http://localhost:8345/mcf-api-service/json/repositoryconnectionhistory/myConnection?report=simple
But I am not sure if I am using them correctly or how they should be attached to the URL, because it is not mentioned in the documentation.
The problem is also that I don't receive any error, but an empty object, so it is difficult to debug. The API returns an empty object even for a non-existing connection.
However it works for resources, which doesn't have any attributes, e.g.:
http://localhost:8345/mcf-api-service/json/repositoryconnectionjobs/myConnection
or
http://localhost:8345/mcf-api-service/json/repositoryconnections/myConnection
Thanks in advace for any help.
I also wrote a message to ManifoldCF team and they gave me an answer. So I summed up it for you below.
Query parameters go after the fixed "path" part of the URL and are of the form ?parameter=value&parameter2=value2...
So in the same way as in any other URL.
The problem was that I didn't supply the activity(s) that I wanted to match. Possible activities are e.g. fetch, process. My example:
http://localhost:8345/mcf-api-service/json/repositoryconnectionhistory/myConnection?activity=process&activity=fetch
Finally, the reason why I didn't get an error when I used a connection name that is bogus is because the underlying implementation is merely doing a dumb query and not checking for the legality/existence of the connection name.

How to get the original request URI in api gateway?

From a lambda implemented api gateway resource, how to get the original request URI. Or even just the original path?
Lacking a better way I'm currently using the following three variables that I pass down to the lambda using the default request template:
$context.resourcePath contains the path with variable names ex: "/blah/{var}"
$input.params().path contains the variable names and values ex: {"var":"something"}
$context.stage contains the stage ex: "prod"
That's quite a hassle since it requires path variable substitution to get the original call path:
/prod/blah/something
How can I get the original URL or URI?
I'm not finding anything in the documentation that lets you get the original call URI. I can add a feature request to consider adding it. Can you describe your use case. Why do you want to get the original URI?
I found a 'workaround'.
If you create a custom domain name with a BasePathMapping, and call the API using this custom domain, the original request uri actually has your stage name in there:
Call directly to the API gateway:
curl -v 'https://some-id.execute-api.eu-central-1.amazonaws.com/v1/ping'
...
request.url: https://some-id.execute-api.eu-central-1.amazonaws.com/ping'
But if we call it through te custom domain (which is actually a cloudfront distribution):
curl -v -X GET https://api.our.domain.name.com/v1/ping
...
request.url: https://api.our.domain.name.com/v1/ping
In my opinion, the direct call gives you an INCORRECT request url in the lambda function, as the url very clearly has the stage name in there.
This breaks the routing middleware of at least flask.
Any update on the feature request?

Is it possible to use wildcards or catch-all paths in AWS API Gateway

I am trying to redirect all traffic for one domain to another. Rather than running a server specifically for this job I was trying to use AWS API Gateway with lambda to perform the redirect.
I have this working ok for the root path "/" but any requests for sub-paths e.g. /a are not handled. Is there a way to define a "catch all" resource or wildcard path handler?
As of last week, API Gateway now supports what they call “Catch-all Path Variables”.
Full details and a walk-through here: API Gateway Update – New Features Simplify API Development
You can create a resource with path like /{thepath+}. Plus sign is important.
Then in your lambda function you can access the value with both
event.path - always contains the full path
or event.pathParameters.thepath - contains the part defined by you. Other possible use case: define resource like /images/{imagepath+} to only match pathes with certain prefix. The variable will contain only the subpath.
You can debug all the values passed to your function with: JSON.stringify(event)
Full documentation
Update: As of last week, API Gateway now supports what they call “Catch-all Path Variables”. See API Gateway Update – New Features Simplify API Development.
You will need to create a resource for each level unfortunately. The reason for this is API Gateway allows you to access those params via an object.
For example: method.request.path.XXXX
So if you did just /{param} you could access that with: method.request.path.param but if you had a nested path (params with slashes), it wouldn't work. You'd also get a 404 for the entire request.
If method.request.path.param was an array instead...then it could get params by position when not named. For example method.request.path.param[] ...Named params could even be handled under there, but accessing them wouldn't really be easy. It would require using something some sort of JSON path mapping (think like what you can do with their mapping templates). Sadly this is not how it's handled in API Gateway.
I think it's ok though because this might make configuring API Gateway even more complex. However, it does also limit API Gateway and to handle this situation you will ultimately end up with a more confusing configuration anyway.
So, you can go the long way here. Create the same method for multiple resources and do something like: /{1}/{2}/{3}/{4}/{5}/{6}/{7} and so on. Then you can handle each path parameter level if need be.
IF the number of parameters is always the same, then you're a bit luckier and only need to set up a bunch of resources, but one method at the end.
source: https://forums.aws.amazon.com/thread.jspa?messageID=689700&#689700
Related to HTTPAPI that AWS introduced recently, $default is used a wildcard for catching all routes that don't match a defined pattern.
For more details, refer to: aws blogs
You can create a resource with path variable /{param}, and you can treat this as wildcard path handler.
Thanks,
- Ka Hou

GWT RequestFactory: Send changes twice

I need your help with the gwt requestfactory
considering following scenario:
I get an existing entity (let's say a invoice) from the server:
InvoiceEntityProxy invoice = request1.getInvoice();
I want to make some changes, so I edit it with a new request:
InvoiceEntityProxy editableInvoice = request2.edit(invoice);
//make some changes to editableInvoice
Now I send the changes made with the second request to the server, to create a preview:
request2.createPreview(editableInvoice);
When the request is sent, the invoice proxy is frozen and I re-enable editing by assigning the proxy to a new request:
editableInvoice = request3.edit(editableInvoice);
If everything is okay, i want to update the proxy and send it to the server, using the latest request:
request3.update(editableInvoice);
But the changes never arrive on the server, because the latest request (request3) doesn't know anything about the changes made to the proxy assigned to the request2.
I thought about following solutions:
I could redo the changes on the latest proxy. But for that, I've to iterate over all attributes and set them again (not very friendly solution, because I've to adjust the method each time I add some attributes to the proxy)
Another approach would be to send the proyx without an id to the server and send the id as second parameter of the update-method. But this would be a shame, because not only the deltas would be sent to the server (which is one of the greate features of the requestFactory).
So what is the best and most common practice to let the request3 know about the changes already made to the proxy, when it was assigned to another request.
You simply forget to call fire(). Example
request2.createPreview(editableInvoice).fire();
Bear in mind that if the following request depend on the result of the previous one, you should put your code in the OnSuccess methode because the request is asynchronous
It's also possible to append multiple requests
EDIT
It important to use the same request for the edit and fire operations. So replace this line
request.update(editableInvoice);
with
request3.update(editableInvoice);
Nice! I found the solution for my problem.
I still have an instance of the original proxy, because the edit() method of the context always return a new instance of the proxy. So I save the original proxy before sending any request.
After each successful request, I re-enable editing the proxy by call the edit method again:
editableInvoice = request3.edit(editableInvoice);
Now the crux:
I can set the original proxy of a proxy, which is used to consider if it changed and what changed. This is done by using AutoBean and set the PARENT_OBJECT Tag like this:
AutoBean<InvoiceEntityProxy> editableInvoiceBean = AutoBeanUtils.getAutoBean(editableInvoice);
AutoBean<InvoiceEntityProxy> originalInvoiceBean = AutoBeanUtils.getAutoBean(originalInvoice);
editableInvoiceBean.setTag(Constants.PARENT_OBJECT, originalInvoiceBean);
On the next request all changed properties are send to the server again.
Thank you for your help and thank you for the hint with the AutoBean #Zied Hamdi
You also can use AutoBeans to duplicate the object before you start changing it. You can keep the original one untouched then request.edit() it and apply changes (introspection like changes) from the "dirty" object.
You'll maybe have to do some research on how to handle EntityProxies since they are "special AutoBeans" : I had to use special utility objects to serialize them to json (available in GWT). So there might be some special handling in doing a deep copy too.
There is an issue maybe with GWT keeping only one version of each EntityProxy (I never checked if it is global or only in the context of a request)

RESTful, efficient way to query List.contains(element)?

Given:
/images: list of all images
/images/{imageId}: specific image
/feed/{feedId}: potentially huge list of some images (not all of them)
How would you query if a particular feed contains a particular image without downloading the full list? Put another way, how would you check whether a resource state contains a component without downloading the entire state? The first thought that comes to mind is:
Alias /images/{imageId} to /feed/{feedId}/images/{imageId}
Clients would then issue HTTP GET against /feed/{feedId}/images/{id} to check for its existence. The downside I see with this approach is that it forces me to hard-code logic into the client for breaking down an image URI to its proprietary id, something that REST frowns upon. Ideally I should be using the opaque image URI. Another option is:
Issue HTTP GET against /feed/{feedId}?contains={imageURI} to check for existence
but that feels a lot closer to RPC than I'd like. Any ideas?
What's wrong with this?
HEAD /images/id
It's unclear what "feed" means, but assuming it contains resources, it'd be the same:
HEAD /feed/id
It's tricky to say without seeing some examples to provide context.
But you could just have clients call HEAD /feed/images/{imageURI} (assuming that you might need to encode the imageURI). The server would respond with the usual HEAD response, or with a 404 error if the resource doesn't exist. You'd need to code some logic on the server to understand the imageURI.
Then the client either uses the image meta info in the head, or gracefully handles the 404 error and does something else (depending on the application I guess)
There's nothing "un-RESTful" about:
/feed/{feedId}?contains={imageURI}[,{imageURI}]
It returns the subset as specified. The resource, /feed/{feedid}, is a list resource containing a list of images. How is the resource returned with the contains query any different?
The URI is unique, and returns the appropriate state from the application. Can't say anything about the caching semantics of the request, but they're identical to whatever the caching semantics are of the original /feed/{feedid}, it simply a subset.
Finally, there's nothing that says that there even exists a /feed/{feedid}/image/{imageURL}. If you want to work with the sub-resources at that level, then fine, but you're not required to. The list coming back will likely just be a list of direct image URLS, so where's the link describing the /feed/{feedid}/image/{imageURL} relationship? You were going to embed that in the payload, correct?
How about setting up a ImageQuery resource:
# Create a new query from form data where you could constrain results for a given feed.
# May or may not redirect to /image_queries/query_id.
POST /image_queries/
# Optional - view query results containing URIs to query resources.
GET /image_queries/query_id
This video demonstrates the idea using Rails.