Running SOAP and RESTful on the same URL - http

Say we have a website that responds to a host header "kebab-shop.intra.net"
Is is possible to have both SOAP and RESTful in this URL?
That is, both of these are handled within the deployed code.
kebab-shop.intra.net/takeaway.asmx
kebab-shop.intra.net/kebab/get/...
I've been told this can't be done, without much explanation. Like this answer. This could be, I'm a database monkey, but I'd like some thoughts on what options I do or don't have please.
Thoughts so far
Separate host headers eg add kebab-shop-rest.intra.net
Separate web sites
Ideally, I'd like to have one web site, one URL domain name, one host header. Zero chance?
This is IIS 6 with .net 4. And we have some large corporate limitations that mean we are limited to a zip file to drop into the relevant folder used by the web site. This is intended to allow our clients to migrate without incurring the large corporate support, infrastructure and deployment overhead. The co-existence will only be for a month or three.
Edit: I'm asking because I'm not web developer. If my terms are wrong, this is why...
So... I want both SOAP and REST on kebab-shop.intra.net on IIS 6 without complexity.

That is, both of these are handled
within the deployed code.
* kebab-shop.intra.net/takeaway.asmx
* kebab-shop.intra.net/kebab/get/...
Yes, that should definitely be possible. If you have a single WCF service, you could easily expose two separate endpoints for the same service - one using e.g. basicHttpBinding (roughly equivalent to ASMX), and another with webHttpBinding (REST).
The complete URL's must be different - but the first part can be the same, I believe.
If you're hosting in IIS6, you need one virtual directory and that will partly dictate your SOAP endpoint - it will have to be something like:
http://kebab-shop.intra.net/YourVirtDir/takeaway.svc
(or: http://kebab-shop.intra.net/YourVirtDir/takeaway.asmx if you insist on using an ASP.NET legacy webservice).
and the REST endpoint can live inside the same virtual directory and define URI templates, e.g. you could have something like:
http://kebab-shop.intra.net/YourVirtDir/TakeKebab/gbn
or similar URL's.
However: checking this out myself I found that you cannot have both service endpoints "live" off the same base address - one of them has to have another "relative address" associated with it.
So either you add e.g. "SOAP" to your SOAP endpoint
http://kebab-shop.intra.net/YourVirtDir/takeaway.svc/SOAP/GetKebab
http://kebab-shop.intra.net/YourVirtDir/TakeKebab/gbn
or you add something to your REST service
http://kebab-shop.intra.net/YourVirtDir/takeaway.svc/GetKebab
http://kebab-shop.intra.net/YourVirtDir/REST/TakeKebab/gbn

I don't see a reason why you can't. Typìcally your SOAP endpoints will be one specific URLs per service, whereas for resources exposed via REST you will have one URL per resource (following 'URL patterns').
Example URLs for SOAP:
http://kebab-shop.intra.net/soap/service1
http://kebab-shop.intra.net/soap/service2
Example URL patterns for REST:
http://kebab-shop.intra.net/rest/{resourcetype}/{id}/
e.g.: http://kebab-shop.intra.net/rest/monkeys/32/
etc...

Related

Serving static content programmatically from Servlet - does the spec have anything available or i should roll a custom one?

I have a db with original file names, location to files on disk, meta data like user that owns file... Those files on disk are with scrambled names. When user requests a file, the servlet will check whether he's authorized, then send the file in it's original name.
While researching on the subject i've found several cases that cover that issue, but nothing specific to mine.
Essentially there are 2 solutions:
A custom servlet that handles headers and other stuff the Default Servlet containers don't: http://balusc.omnifaces.org/2009/02/fileservlet-supporting-resume-and.html
Then there is the quick and easy one of just using the Default Servlet and do some path remapping. For ex., in Undertow you configure the Undertow subsystem and add file handlers in the standalone.xml that map http://example.com/content/ to /some/path/on/disk/with/files .
So i am leaning towards solution 1, since solution 2 is a straight path remap and i need to change file names on the fly.
I don't want to reinvent the hot water. And both solutions are non standard. So if i decide to migrate app server to other than Wildfly, it will be problematic. Is there a better way? How would you approach this problem?
While your problem is a fairly common one there isn't necessarily a standards based solution for every possible design challenge.
I don't think the #2 solution will be sufficient - what if two threads try to manipulate the file at the same time? If someone got the link to the file could they share it?
I've implemented something very similar to your #1 solution - the key there is that even if the link to the file got out no one could reuse the link as it requires security. You would just "return" a 401 or 403 for the resource.
Another possibility depends on how you're hosted. Amazon S3 allows you to generate a signed URL that has a limited time to live. In this way your server isn't sending the file directly. It is either sending a redirect or a URL to the front end to use. Keep the lifetime at like 15 seconds (depending on your needs) and then the URL is no longer valid.
I believe that the other cloud providers have a similar capability too.

Make my oracle apex application point to website home page url

I have my oracle apex database application built in a oracle web hosting server. For ex, it is like http://www.myapexhostingserver.com/pls/apex/f?p=4550:1:13225322000472
Here I have created many apex database applications. Now I have specific domains for each of these apex applications. Currently, I have written a redirect in each of these domain settings to my apex application.
For ex,
http://www.domain1.com has a redirect url set to http://myapexhostingserver.com/pls/apex/f?p=162:LOGIN:16888048444232
http://www.domain2.com has a redirect url set to http://myapexhostingserver.com/pls/apex/f?p=165:LOGIN:16888048444232
A redirect is not google friendly. But I cannot purchase oracle web hosting for each domain too. Is there any other good solution available?
Meaning, when I buy a shared hosting server, I can create as many PHP applications I want. But not sure if this is also possible in oracle apex.
Can someone help?
Developing Oracle Apex Applications with Search Engine Visible Designs
This is a discussion on the issues with the varying style of APEX Application url syntax. There also is an explanation of how APEX work space namespaces are organized to show how application url's can be customized using a single database instance.
Comments: Some Internet searches can yield an answer that you're looking for. There are a number of developers and consulting gigs out there who have tackled the problem of converting between the popular, canonical url paths and the notation used by Oracle APEX.
Some search terms that proved useful include: oracle apex pretty url, url mapping, and http url mapping plsql. The most useful guides were examples in Oracle PL/SQL, but you can also dive deeper and set up rules on the web server engine (i.e., Apache HTTP Server) that re-interprets URL requests so that the APEX styled addresses are masked. This isn't necessary, but some techniques such as "url remapping" are among the possible solutions.
What this post is NOT is a guide on specifics of Search Engine Optimization (SEO), which may be distantly related to the OP's question about "Google Friendliness", but is beyond the scope of this solution guide.
Are Oracle APEX Websites Search Engine Friendly?
A comment quoted directly from the original post was worth researching and addressing. This is mostly an incorrect conclusion.
A redirect is not google friendly.
This actually depends on how you set things up on your APEX website. Redirects are one way of managing incoming traffic that use alternate url naming schemes, but this is not the only approach.
Some Successful Blogs and Websites Done in Apex:
Some online groups such as the APEX developer team with APEX Ninjas continue to report growing referrals from search engines such as Google without many changes to the way their Oracle APEX powered site and blog.
Another good example is the active APEX website: "ASK Tom", which was created by Oracle's Tom Kyte. This site has run on APEX for many years now and references to pages on this website continue to appear on search engine result pages the familiar APEX style url formatting from the "ASK Tom" website.
Using Better Navigation URLs for Clarity
Web server REDIRECTS are one approach to mapping cleaner url address syntax on top of an Oracle Apex Listener. We use the Abyss Web Server Engine, which is a light-weight http server that sits on the front of our company APEX application server. It's not absolutely necessary, but we chose it for its simplified management of a singlular web server task. Redirects work fine for us as well. Though we have not explored further, advanced features such as virtual hosting and url rewriting rules may take you further regarding your requirement to separate out multiple TLDs (primary domains) or C-NAMEs (sub-domains) on the same Apex listener instance.
The ugliest of the URL forms in APEX Applications is the default. It is decipherable, but not friendly to the human eye or simple enough to remember. Here is an example shot of the URL assigned to the HOME page of my application named: APEX-LAB-PUB
This is a common format of the URLs that an Oracle APEX web server will interpret. So the general format to observe is that everything after the clause: f?p=...
http://somedomain.com/pls/apex/f?p=1312786:5:987529480
By using the alternative option of setting ALIAS names, you can create short-cut url forms in the same layout, but with human readable alias assignments:
This is good, but there is also a common practice which uses Oracle Apex's native REST Web Service listener so that internal and external links look simpler. Simplified url syntax can also make setting up redirect hooks cleaner and more organized.
Oraganizing APEX Application Websites Using REST Web Services
To develop this example, I used Oracle's free Apex hosting tier. Although it has some limitations on what features are available, RESTful web services are enabled on the Apex listener of this platform, which is what we need.
Mapping a Web Service URI to an Apex URL Request
This is the url syntax we will be using will look something like this:
https://apex.oracle.com/pls/apex/...(workspace)/...(uri request)
Uniform Resource Identifier (URI)
This is the part that will be appended to the end of the base url of the Oracle Apex hosting listener. The example below is just a generic template:
Generic URI Syntax This Solution URI
hr/employees/{ID} display/{app}/{page}
|_|_________|____| |______|____________|
| | | | |
| | -Handler Bind Variable | -Handler Bind Variable(s)
| | |
| - URI Template - URI Template
|
- Module URI Prefix
-- RESTful Service Design Summary
Module Name: superEasyURL
URI Prefix (optional): (none)
URI Template: display/{app}/{page}
Handler Method: GET
Handler Source Type: PL/SQL
Handler Source:
declare
url varchar2(500);
baseurl constant varchar2(2000):=
'https://apex.oracle.com/pls/apex/f?p=';
begin
url:= baseurl || :app || ':' || :page;
:URL := url;
:STATUS := 303;
end;
Note: You will also need to set two OUT parameters for this REST Service to represent the two bind variables in the above PL/SQL statement for the values of URL and STATUS:
About the HTTP 303 Status Header Code
There is another kind of HTTP status code called an HTTP 303. You can use APEX to deliver pages and content that are not redirects. Oracle Application Express and its RESTful Web services can receive traditional url requests that convert to the APEX format on the back-end.
303 See Other has been proposed as one way of responding to a request for a URI that identifies a real-world object according to Semantic Web theory (the other being the use of hash URIs).
For example, if http://www.example.com/id/alice identifies a person, Alice, then it would be inappropriate for a server to respond to a GET request with 200 OK, as the server could not deliver Alice herself. Instead the server would issue a 303 See Other response which redirected to a separate URI providing a description of the person Alice.
Reference Excerpt: Wikipedia.com
Demonstration of a Working Example
This is an example created in my personal, Oracle hosted workspace. This is the url which will be interpreted by the REST Service built earlier.
https://apex.oracle.com/pls/apex/rgpascual/display/{app}/{page}
|_________|
|
|
- Workspace ID String (required by the listener) -
Note that on the shared instance, an additional reference to the user's workspace name was required to make this translation happen. I am not 100% sure if it is required, but I was able to complete this demo by using it in the final path references.
Display of: HOME page (aliased) from the APEX-LAB-PUB Application (aliased as: APEXLABPUB01).
Conclusions, Questions and General Advice
The efforts of this post offers the possibility of using pretty url syntax to represent navigation links within an Apex Application website. Instead of the default notation defined by Oracle, a navigation link list may look like:
Note: These links do not work. They are just to illustrate the advantages of this presented solution.
Home
Actual Requested URL:
someapexserver.../pls/apex/mywork/display/new-app/home
About Us
Actual Requested URL:
someapexserver.../pls/apex/mywork/display/new-app/about
Contact
Actual Requested URL:
someapexserver.../pls/apex/mywork/display/new-app/contactus
Associates
Actual Requested URL:
someapexserver.../pls/apex/mywork/display/new-app/associates
Business Ops
Actual Requested URL:
someapexserver.../pls/apex/mywork/display/new-app/businessops
Now, referring links and navigation is uniform and consistent using the URI template chosen in the initial design of this solution.
Additional Questions: Application Capacity of a Single Apex Instance
There was an additional question about the way that Oracle Apex manages applications created in a single instance.
... Meaning, when I buy a shared hosting server, I can create as many PHP applications I want. But not sure if this is also possible in oracle apex.
You should consider reviewing the Apex documentation put out by Oracle to understand how the Apex security framework affects the possibilities or organizing multiple applications created from the same database instance.
A few things to note however:
A single database installation, or INSTANCE can contain multiple divisions called WORKSPACES. Workspaces by default cannot see what is in other workspaces but applications within may share access to the same database schemas on the back-end.
A WORKSPACE may contain any number of APEX applications. Each application enabled with login security may have its own user authentication or it may use the "native" authentication process. Without further configuration, Application User accounts in the same Workspace will have have access to the other apps in the same workspace.
The USER NAMESPACES of each Workspace are separate, i.e. there may be two user accounts with the same name between two or more different Workspaces. (a user named ADMIN in both WORKSPACE1 and WORKSPACE2 are NOT the same user.)
NAMED DATABASE USERS may have access across other multiple Apex workspaces. A user defined this way is unique across every workspace and application permitting its access. Access users defined as Named Database Users are defined unique across a given database INSTANCE.
So in conclusion, Apex is designed to support multiple applications similarly to hosting on a single, shared hosting set up. Chances are however, if you are looking for the amount of control you describe in the OP, your shared hosting will most likely be your own Dedicated Server solution, VPS (Virtual Private Server) or AWS (Amazon Web Services) host.
You will need a host with enough access to server resources to: (a) Permit the installation of Oracle database software on the host. (b) Allow the configuration (opening and/or closing) of server networking ports. (c) Enough server resources to support the active operation of the installed database instance and the web-requests serviced by the accompanying HTTP based listener.
If you want your installation to manage multiple moderately sized and trafficked web applications, you will need a lot more than the minimum server specifications described in the installation instructions of the Oracle database version and edition you choose.

CRM 2011 multiple host names

Is it possible/supported to have a CRM 2011 host work with two different host names? We have tried this, but not everything works perfectly.
Example:
A server with server name "app1".
An AD/DNS entry pointing the host name "crm" to "app1".
When users navigates to "crm" the requests work 99% of the time, but a few internal javascripts in CRM targets the original "app1" server. For example a request from normal edit forms that retrieves the roles. The javascript variable called "*SERVER_NAME*" always has value of "app1", no matter the request URL. A cross-server warning might appear or the functionality may just silently fail.
This also happens when accessing the FQDN of the server, so "app1.mydomain.com" still produces the same result and failing/warning functionality.
I imagine this would be a similar problem when dealing with load balanced installations? How do they handle this? I.e. they target host name X and can get host name Y or Z.
Edit: I've understood that this may be called "domain alias" or "host alias" since it is an active directory entry.
You cannot have multiple hostnames for the CRM system.
You have to specify an address which is used by the CRM system itself, for scripts like you have seen. But it is also used for the Discovery mechanisms.
Multiple bindings in IIS are not supported due to a limitation with the web service endpoint
Open the deployment manager on the CRM server.
Go to Actions -> Properties -> Addresses
Adjust the stated addresses to the one which you use to access the CRM system. These settings are important for the CRM to define its "identity".
If you have configured IFD you configure an additional external identity.
By the way. Depending on your environment it might be necessary to set an SPN. See http://blogs.msdn.com/b/webtopics/archive/2009/01/19/service-principal-name-spn-checklist-for-kerberos-authentication-with-iis-7-0.aspx
Regarding NLB: http://technet.microsoft.com/en-us/library/hh699803.aspx
Daniel Cai seems to have a good way round the problem of getServerURL returning the value held in deployment manager rather than the calling page URL when you have different names used. He has come up with a replacement function:
CRM 2011: Get the Right Server URL in Your CRM Client
This looks like it works for all scenarios with Outlook offline client as well as online browser.

JSONP and sharing cookies from one server to another?

I'm working on an intranet system (.NET 3.5); the main pages are served up from a standard ASP.NET server. I would like to use Ajax on those pages to contact a WCF service running on a different machine, to retrieve data, do CRUD operations - the usual Ajax stuff.
The problem I'm trying to resolve is: can I take cookies which were set by the ASP.NET server, and include them on requests to the WCF service? If so, how?
My understanding is that JSONP bypasses XSS restrictions by "wrapping" the Ajax request within a standard <script src="MyAjaxCall?SomeData=SomeValue"> tag. With that in mind, it would seem I'm at the mercy of the browser as to which cookies (if any) will be included in MyAjaxCall. Since the cookies originate from the ASP.NET server, the browser likely won't include them in the call to WCF.
Since this is an intranet application, I cannot necessarily rely on domain wildcarding (*.mydomain.com) to make sure the cookies are shared across multiple machines - the client may well be accessing machines by their simple network name or even IP address directly.
edit: accepting Julian's answer, since using JS to manually grab a cookie's payload and jam it onto the URL seems like the only way to work-around the restriction (tho it feels somewhat inelegant :)
You're perfectly right in assuming you'll have problems with cookies.
The only workaround is to actually pass the values of interest into the query string of the JSONP request. Which means you'll have to inspect cookies client-side, extract the data you need from them and then append it to the url "by hand".

Who is calling my WebService?

I have a web service that is on an internal server. It can be called from any website on our network.
More and more developers are starting to use it. Current probably 20+ pages use this service, and the number is growing fast. I can see a year from now, someone asking what pages are using this service and what methods.
I would like to log the url of the pages that use my web service as the request come in.
It would also be nice to know the method they are calling.I need to do something in such a way, that it does not affect the client web sites.My first thought was that I could write some code in the global.asax.
I have added some code to the Application_BeginRequest to log the request object details, but there does not appear to be anything about the requesting url.
What am I missing? Should I be looking at a different object?
Thanks.
Without disrupting existing users this is going to be difficult. The httpContect.Current.RequestUrl will just return the URL used to call your web service, not which web page called it.
The closest you can do without disrupting existing apps and forcing developers to change them is to grab the HttpContext.Current.Request.UserHostAddress, so you can at least get the IP of the machine calling your service.
Beyond this, what you might want to consider is adding a parameter to your functions for "CallingApp" and then log that in your code. That's pretty much what we did once re realized that we needed to know which apps are calling our service. We actually have an application monitoring service that uses a GUID for every new app we develop, and we pass that GUID to any web service. It[s extra work but to us it was critical because it allows us to know which apps will be affected when we need to perform updates or take the app server down for maintenance.
Edit - added
As a side note, at the point we realized we needed to track this, we had already been using web services for about a year. When faced with the same problem, we created a new set of web services, and included the extra field for the calling app in all of the new services, and then slowly went back and changed the older programs to point to the new services.
IN retrospect, we wish we had known we would need to do this up front because it created a lot of extra work. I'm guessing you'll be facing something similar if you really want to know exactly who is calling your services.
The only thing you can probably retrieve from the consumer is the IP address without changing your interface.
If you can change this you could do this e.g. by adding authentication and logging who is calling what, or by having some simple "token" principle.
However both methods require you to change the interface and therefore break backwards compatibility - which you should never do.
By always ensuring both back and forward compatibility you should not need to know exactly who is calling your service, but only that it is actually used.
#David Stratton
Thanks for your help. I think your suggestions were great. I accually did something very different, after your answer gave me some new ideas.
I should have mentioned that I was generating the web proxy that most of my users were using to make calls against my web service. My client in general do NOT use the proxy that Visual Studio creates.
Here is what did:
I generated my web proxy client again, and added calls to log the httpcontext of the client before every call. Because the proxy is running on the client, he had access to everything I needed. That allowed me to record everything about the client and the specific call they were making. I realize this would not work for most cases. But all of my clients are internal web sites.
It also had the advantage in that the clients did not have to modify their code at all. I just gave them all a new DLL. Problem solved. I get all the tracking data I want, and they did not have to modify their code.
I was stuck trying to solve the problem from the web service's point of view.
I realize that there is still a whole in this implementation, because someone does not have to use my client proxy to call my service. I guess I could force that at some point in the future. For now, they could let Visual Studio genereate a web proxy for my service. However, if they do that I guess I don't care. That is not the recommened way to call my service. I think the only one doing that is an ASP.NET 1.1 web site. When they upgrade, they will probably switch to my generated proxy.
Without implementing some sort of authentication, there isn't a guraenteeted way of knowing exactly who is calling your service - web metrics are the only way you can gauge what volume of traffic is hitting your service.
I'm sure you already know this but the whole point of a web service isn't to know or care who is calling it.
I have successfully used ...
Dim strReferrer As String = HttpContext.Current.Request.UrlReferrer.AbsoluteUri
to get the calling page that called my WEB API 2 Web Service.

Resources