Datasnap method name [duplicate] - rest

I've written a REST server in Delphi XE (using the wizard) and I want to change the URLs a bit so that instead of having
http://192.168.1.84:8080/datasnap/rest/TServerMethods1/GetListings
I get something that looks more like http://192.168.1.84:8080/GetListings
Is there a nice easy of doing this?

The naming convention is (Delphi XE3):
http://my.site.com/datasnap/rest/URIClassName/URIMethodName[/inputParameter]
You can easily change the "datasnap" and "rest" part of the URL in the TDSHTTPWebDispatcher component properties. You can change the Class Name and Method Name of the URL by simply changing the name of your class and method. However, you still have to have 4 components to the URL, so for example it could be:
http://my.site.com/api/v1/People/Listing
See here:
http://docwiki.embarcadero.com/RADStudio/XE3/en/REST#Customizing_the_URL_for_REST_requests

You could put IIS or Apache in between to accomplish this, and indeed rewrite the URL to point to your service the way you like.
That provides some more advantages anyway (security and scalability mostly). For example, you can create a fail-safe setup with double servers, or you can create multiple machines with your service, and have your web server do the load balancing for example.
You'll get extra logging capabilities, and if you easily want to serve other web content it's easy to have a full fledged web server anyway.

URL rewriting is usually done in the web server configuration, in Apache using entries in the .htaccess file

Related

Best practices for REST API that access multiple environments

When writing a RESTful API that needs to access different environments such as a lab/test database and a production database, what's the best practices around setting up the API?
Should there be a #PathParam?:
/employee/{emp_id}/{environment}
/{environment}/employee/{emp_id}/
Should there be a #QueryParam?:
/employee/{emp_id}/?environment="test"
/employee/{emp_id}/?environment="prod"
Should there be a field in the payload?:
{"emp_id":"123","environment":"test"}
{"emp_id":"123","environment":"production"}
In fact I see two ways to handle this. The reason to use one or the other corresponds to what is the most convenient to implement in your RESTful application.
Using a path parameter
With this approach, it should be a path parameter at the very beginning of the resource path. So URL would be like this: /{environment}/employee/{emp_id}. Such approach is convenient if you have several applications deployed under different root paths. For example:
/test: application packaged with the configuration for the test environment
/prod: application packaged with the configuration for the production
In this case, applications for each environment are isolated.
Using a custom header
You could also a custom header to specify on which environment to route. Github uses something like that to select the version of the API to use. See this link: https://developer.github.com/v3/#current-version. It's not exactly the same thing but you could have something like that:
GET /employee/{emp_id}
x-env: test
A reverse proxy could handle this header and route the request to the right environment.
I'm not convinced by the approach within the payload since an field environment isn't actually a part of the representation for element resource employee. Regarding the query parameter approach, it's similar since such parameters apply to the request on the resource.
Hope it helps you,

Portal URL from Portlet

Is it possible to get the Portal base URL (like http://www.thisismyportal.com) from a Portlet using Portlet 2.0 API?
Right now I'm planning to manually build it concatenating PorletRequest.getServerName(), PortletRequest.getServerPort() and PortletRequest.getContextPath(); but it seems kind of clumsy (and there's no PortletRequest.getProtocol())
While it is clumsy, it is the safest way to construct the URL; and while there is no PortletRequest.getProtocol() method, you can conclude the protocol using the PortletRequest.isSecure() method.
I would advise against using an external configuration for the base URL, for a couple of reasons.
First, it would be yet another configuration item for you to maintain across environments (test, integration, production and so forth). There's very little justification to hold, in configuration, something that is fully reproducible using the current request.
Second, under certain circumstances, it might be impossible to designate a particular URL as a "base URL" for the portal. An example would be the case in which the portal server is associated with multiple hosts, or multiple host aliases.
We had those configuration properties in Resource Environment Provider for the purpose of generating external URLs for sending them in emails. It was specific solution and it wasn't a problem for us as we had other properties stored there as well so we knew it will be available at runtime. I don't know if that suits your needs. It depends on your scenario.
Also, we used https only during login, so we always generated http URLs.
Hope this helps.

Can REST be used instead of URL Rewrite in CF10?

Can the REST support in CF10 be used to replace the use of URL Rewrite / ModRewrite for SEO-friendly URL? Write a thin layer that defines the GET and POST method, and <cfinclude> in the correct page?
Or would it tax the server too much and better leave it to the web server to deal with?
Once in CFML, it'd be much easier to be version controlled and maintained.
Thanks
If I understand what you are saying (and perhaps I do not) you would create a handler that would intercept a request, parse out the variables, then request the appropriate page via REST? If that's what you have in mind then I'm not sure I follow what you would gain by this. REST (in general) is more of a generic HTTP API for getting at methods - not so much a page / content paradigm (thought I suppose it could be).
If what you are looking for is to use CF as an rewrite SEO URL handler you can do this now. To use an IIS example, you can create a "custom 404" handler - a CFM page - that gets all the requests that are not tied to a specific document. The handler teases out the variables by parsing through the URL, then "includes" the correct cfm Code or page. That sounds a bit like what you want - but it's not really REST.
Perhaps you are thinking of doing some sort of CFHTTP call where you grab the content you need by constructing the query string from the URL. So if someone loads a url like:
blah.com/productid/550
You could write code like so -
<cfhttp
url="http://blah.com/index.cfm?#listfirst(cgi.script_name,'/')#=#listlast(cgi.script_name,'/')#"/>
<cfoutput>#cfhttp.filecontent#</cfoutput>
While this would do the trick you would be better off using cfinclude rather than this approach. An approach like the one above would actually generate an additional thread per request - one thread for the browser's request and another for the cfhttp request.
Finally I would suggest politely that URL Rewrite (in apache or IIS) is more efficient and more "conventional" and therefore probably a better choice in general.
#Henry
REST is not a replacement for the URL rewriting.
First of all the REST URLs have a format.
http://localhost:8500/rest/App_Name/Rest_Path
"rest" part is mandatory. If you want to change "rest" you can change it in the web.xml (Change the URL Mapping).
App_Name is not mandatory. A server can have a default rest application. For default applications you do not need to specify the AppName. For accessing other (non-default) rest applications, you should specify, the AppName. You can make an application default in the Rest Service registration page in the admin.
Rest_Path identifies the CFC and the function in the CFC that needs to be invoked on the HTTP call.
If these URL format is acceptable, then the URL of these formats can be mapped to a specific function in a CFC. When ever an HTTP call is made to the URL, the corresponding CFFunction will be invoked. By using REST, you are accessing a function in the CFC. It is not possible to access a CFC or a CFM directly in this way. But in the function you can implement whatever you want(Like invoking a CFC, Invoking another CFM etc.).
Does this reply answer your question?
Thanks,
Paul
Even if one could do this, I'd say it's co-opting the wrong tool to do the wrong job. URL rewriting is the web server's job, not the CF server's, and the web server will be a hell of a lot better at it than CF will be. CF's REST interface is for building APIs, not for doing URL rewriting.
If one was to want to handle URL rewriting with CF, then using the 404 handler or onMissingTemplate() handler would be a better fit here, would it not? At least you're using a tool intended for the job (if not the best one).
As for version control... an .htaccess file is just a text file, like a CFML file is. I've not looked too closely at IIS's rewrite module, but can it not use a text file to configure / maintain its rewrites? Obviously Apache can, and we use Helicon's ISAPI Rewrite module which uses an mod_rewrite-compatible .htaccess file.
It seems to me like you're trying to make the developer's job easier by using an approach that would penalise the production performance. "Making the developer's life easier" should never be grounds for compromising the production environment (IMO, obviously).

What is the underlying technology behind ServiceAsync interface?

I developed a web application (works properly) which registers a user to the system and allows user to upload a file to system via https. The client side code is totally developed by using GWT 2.4 and the back end is several servlets. Except the upload code, all the client-server communications are done via using ServiceAsync interface as it is the common practice in GWT. The upload code is based on a form which is communicating with the upload servlet directly.
This project is developed as a course work and my Professor is keen on knowing the underlying architecture of google web toolkit specificly focused on the client-server communication. His question was,
"How the client code knows the server's url so that all the communication is done?"
His question is legitimate for the ServiceAsync interface. I am calling a function on the server side which seems interesting to him and he wants to know the underlying process behind it.
For uploading, I just defined uploadForm.setAction(GWT.getModuleBaseURL()+"upload"); where upload is the name of the upload servlet in web.xml.
I told him that the compiler generates Javascript code which contains all the web application code (whole system developed dynamically) and the url to the servlet is placed in that script file however the answer did not satisfy him. Please let me know the inner facts of the client-server communication with GWT.
Please give me some answers that can help my Professor to understand GWT's asynchronous client-to-server RPC communication.
The underlying technology is shown here as a diagram. Google says "GWT provides an RPC mechanism based on Java Servlets to provide access to server side resources. This mechanism includes generation of efficient client and server side code to serialize objects across the network using deferred binding."
The client knows the URL to query because you would have annotated your service interface with a #RemoteServiceRelativePath tag. This associates the service with a default path relative to the module base URL. That URL is where Javascript sends your request.
There's a lot more to learn about GWT's RPC if you care to, and you can start picking it apart here and here.
There are multiple ways in GWt how to bind RPC service to the specific url.
First is an annotation #RemoteServiceRelativePath which is placed on synchronous interface. Using deferred binding rule GWT will discover this URL and will set it to the service instance automatically.
Second is casting instance of GWT-RPC async service to the ServiceDefTarget and setting an url manually.
But this answer alone will not satisfy your professor, because most likely he will want to know some other details, so I recommend you to learn how exactly GWT-RPC works.
Regarding the basic question of how the client knows the url of the server, it sounds as though the professor may be asking about the full url of the site (the domain name), and not just the sub-directories for the services as they are defined in #RemoteServiceRelativePath and the web.xml.
For this more fundamental aspect of the question, I think the "Same Origin Policy" (SOP) that browsers have for javascript security could be an important part of the answer. This is explained in one of the GWT FAQs. The first thing that the browser is doing on the client side (after the HTTPS connection is established, which I think could be another important part of the answer) is reading the host html file, where the bootstrap nocache.js file is referenced. Once this file is loaded, the SOP is going to guarantee that all of the subsequent JS application files are coming from the same server as the bootstrap and the host html files. Once the application files are loaded, then everything is happening within that context, with specific internal url paths being defined for RPCs as already mentioned.

GWT: add-linker (cross-site) doens't work with Server code!

I am trying to do some cross-site in GWT.
According to GWT:Same Origin Policy I've added to the module xml file.
It is working okey as long as I am not calling any GWT remote service (using GWT-RPC), but when I try to call any remote service, I got no response!
Any one know how to fix cross-site issue in GWT with GWT remote services?
Thanks in advance!
Steve's answer is correct, however there is one other option you can consider which is the best approach if you want to require authentication for server interaction without using OAUTH. The main point is that the cross-site linker doesn't bypass the SOP, but allows you to host the index.html on a different site than the JS code so that you can have the JS code and servlets on one server and load them from another. To get around the SOP you can use a method called JSON with padding or JSONP. Essentially what it does is use a script tag to inject a foreign request into the environment by wrapping the requested data in a callback. To do this you can use one of many server-side implementations such as Jersey. GWT 2 includes a JsonpRequestBuilder object which does all the client-side work for you and can be used in the same way as RequestBuilder. See this article for a tutorial.
If you want to access some other server (example.com) from your GWT app, then you'll have to do an RPC to your server, and in your server-side code, you'll have to make another HTTP call to the example.com page you're looking for.
The page you linked to regarding cross-site linking outlines that adding <add-linker name="xs"/> to the module file allows you to split your hosting between 2 servers:
One server for static files (all GWT produced html and js files, and all images)
One server for dynamic calls (all your RPCs go here, and your index.html home page must be here)