logo

Cross-Domain Ajax on Domino

Yesterday I got asked how the Rico Weather Watch widget worked. Obviously it's using Ajax but how can it get the data from Weather.com when Ajax can't work outside the current domain?

Cross domain? This means that JavaScript on codestore.net can't fetch XML from openrico.org for example. Or from codestore.org for that matter, even though it's the same site. To prevent malicious code you can only use Ajax on and within your own website. So how does the Rico weather widget work? Well, the Ajax request is sent to:

http://openrico.org/rico/ajax_weather_info?zip=12345

Whatever this is it's on the same site and it's this server-side script that somehow creates a request to weather.com, streaming the data it receives back to the browser. As far as the browser is concerned it's dealing with the same domain.

So, how to do this in Domino? Well, we could call an agent which streams the data back. In Java this is fairly easy and all the methods are there for easily streaming URLs. The code required is similar to this HTML email code.

However, the poser of the question is like most Domino developers and feels more comfortable using LotusScript. So, how does he open a stream that reads in a certain URL and relays it back to the browser? I've seen this done somewhere recently but can't remember where. A Google found this, but I've not tested it. Anybody done this already?

Comments

  1. My colleague did what you describe - having an agent that retrieves some XML in his example.

    Have a look here:

    {Link}

    His example only works in IE I am afraid - it displays the contents of an RSS feed embedded in the page.

  2. Been there. Done that.

    (Don't have the code handy here at the office. Will post a link later when I get home)

    The call was done to an Agent. Inside the agent was GetDocumentByURL. It then passed the resulting code into a filter that actually read the contents of the returned page. (Use Abstract on the RT item).

    I then spat out the relevant details via simple print statements. The first line should be "Content-type:text/xml" followed by an empty line. Then whatever you want in the way of data.

    I did have a fall back position in case the server failed to load the page, in that i went and got the last returned document and used that. Obviously you can take error checking to the very limit. But do watch out for the hanging page load.

    Caveat: you must have teh Web Retriever enabled on the server otehrwise nothing happens.

    • avatar
    • YoGi
    • Fri 10 Mar 2006 05:45 AM

    You might use JSON to avoid cross-domains problems.

  3. Yogi thats true not sure if the Weather.com service supports the JSON format though.

    Heres a link to a method for injecting the JSON data into the DOM - {Link}

    As an aside - I use the MS XMLHTTP object to do this very thing - grap weather.com data, parse the XML and populate a flash thermometer all in LS. - I have the code if you want it Jake.

    • avatar
    • Jake
    • Fri 10 Mar 2006 06:18 AM

    Jens. And the server-side code is?

    YoGI. Whether we use JSON, text or XML is out of our control. We're retrieving the data from a third party so we can't dictate the format.

    • avatar
    • Jake
    • Fri 10 Mar 2006 06:19 AM

    Mark. Yes please.

  4. The downside of using the msxml or winhttprequest objects from LS is that it can only be used when Domino is on the Windows platform. Granted, that is the most commonly used platform, but Sun, Linux and iSeries (among others) are getting stronger and stronger. I blogged about browsing the web with LS a little while back (Link here: {Link} ) where I use LS only. No OS dependencies. It works great for me, and is not restricted by platform.

    Whatever parsing of the content that is needed can easily be added, and the result printed back to the browser.

    • avatar
    • bill e
    • Fri 10 Mar 2006 07:36 AM

    You don't necessarily need to do serverside code. Encode an iframe in an iframe. Data from the inside iframe might html or xml, but the overlying iframe allows you to get the data inside of it. This works well if you're doing a single "get" type. The inside Iframe can be a hardcoded URL, or somesuch. The inside iframe is understood to be in the same domain, but is referencing a url in a differing domain.

    To dynamically make it work, ala Ajax like, you'd need to inject the iframe url code into the dom, and then simply reload/refresh the outside url.

    I haven't done the 2nd part, but if I'm not mistaken, that's basically what google's doing for their gmailchat for firefox (and using a ms activex object for ie).

    The advantage would be less domino server load, but the disadvantage is say you're working in a closed environment where _some_ end-user pc's may be closed off to outside access, but perhaps the server, and most others in the company are not - basically you're stopping them from getting the content.

  5. I know the preference is for an LS solution, but Java makes it fairly easy to open ports on other servers, like port 80. I did a conversion from a php 'app' to a java agent two years ago that demonstrates opening the port and recieving and processing the stream, all in java, all running on a Domino server. You need to sign with unrestricted access though.

    Like others, I'm at work and don't have the code with me to post. If anyone is interested, email me and I'll make it available over the weekend.

  6. Julian - {Link} has some good Java code for getting a file / resource over HTTP - {Link}

    The slightly harder part will parsing the XML.

    -- bill e I am not sure how this would work, doesn't cross domain security prevent 1 Ifame accessing the contents on another which has data sourced from a different domain? Perhaps if you could point to an example.

  7. Gary Devendorf has some code that used the MS SOAP toolkit. The toolkit builds off of the XMLHTTP object, but you do not have to build your own SOAP wrapper.

    {Link}

  8. Oh, and here is some code I used in an R5 agent to pull data from the National Weather Service in the US.

    Dim sess As New NotesSession

    Dim currWebDoc As NotesDocument

    Dim xmlhttp As Variant

    Dim strxml As String

    Set currWebDoc = sess.DocumentContext

    Set xmlhttp = CreateObject("MsXml2.ServerXmlHttp.4.0")

    Call xmlhttp.open("GET", "{Link} False)

    ' if you have a proxy then use these 2 lines

    Call xmlhttp.setProxy(2,"proxy.address.com")

    Call xmlhttp.setProxyCredentials("user","pass")

    Call xmlhttp.send()

    strxml = xmlhttp.responseText

    Print strxml

    Set xmlhttp = Nothing

    Set xmldom = Nothing

    • avatar
    • bill e
    • Fri 10 Mar 2006 11:53 AM

    Jerry,

    Isn't there an issue between the versions of Java on Domino that restrict the changing of ports? Hence, if you need to bypass a proxy or something, couldn't that be an issue? Just asking.

    Mark,

    Ok, so you you have a page (psuedo html)

    span class overlord iframe src url_to_another_page_in_database_or_domain end_span

    Now, that other page has the contents of just:

    span class innerlord iframe src url_to_outside_domain end_span

    When the page loads, the first iframe loads. In instantiating that, the second url kicks in, and the contents are put on that page, which is then displayed in the client. Now, where it gets tricky is that you can copy the html from outer iframe into your div. It's pretty solid actually.

    I'll put together the working example I have and email it to you.

    • avatar
    • bill e
    • Fri 10 Mar 2006 11:58 AM

    Mark,

    I realized I can't find your email on your website. Ping me at my email link here in this post and I'll respond to you then.

  9. The lack of network IO in Lotusscript is embarrasing. They'll have to get there soon to support consuming web services but there is no reason other then the usual marketing (mis)priorities that we caouldn't have had it for years. The choices boil down to java, msxml or xmlhttp. Unless of coure you are working outside the nsf in which case virutally any language/platform on the planet will work.

  10. @ Mark. Nice. Julian's code is much cleaner than what I had, but uses the same base classes.

    @Bill e

    Really not sure. My environment didn't have a proxy to contend with. However, Julian's class takes proxy config into account, so there apparently is a way to deal with it. If you're buliding something that may one day migrate to an AIX server, I'd go with the java approach. We are going to run smack into that here with some win32 server side dependencies soon.

    • avatar
    • Vince
    • Fri 10 Mar 2006 05:18 PM

    Hi Jake,

    I'm doing it here with Julian's class and with LS to use google for spell checking.

    {Link}

    -Vince

  11. @jake

    @jeff

    still a problem....

    take a look to the end of your blog

    {Link}

    cheers

    makerjoe

  12. @Jake

    This Java Agent retrieves XML (or html) when called like this:

    http://host/path/agent?Openagent&Url={Link}

    The XML then has to be parsed in some way of course. If you look in the source at {Link} you can see anexample.

    Source:

    import lotus.domino.*;

    import java.io.PrintWriter;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.net.*;

    public class JavaAgent extends AgentBase {

    PrintWriter browser;

    public void NotesMain() {

    try {

    Session session = getSession();

    AgentContext agentContext = session.getAgentContext();

    Database db = agentContext.getCurrentDatabase();

    browser = new PrintWriter( getAgentOutput(), true );

    Document doc = agentContext.getDocumentContext();

    Document docToUpdate;

    String docQuery_String_Decoded = doc.getFirstItem("Query_String").getValueString();

    String urlNoAgent = docQuery_String_Decoded.substring( 14 , docQuery_String_Decoded.length() );

    System.out.println("urlNoAgent : "+urlNoAgent);

    String UrlToConnect = urlNoAgent;

    URL url = new URL(UrlToConnect);

    URLConnection uc = url.openConnection();

    BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));

    try {

    sleep(1000);

    }

    catch (Exception e) {System.out.println("Error reading - retrieve(URL url)"); }

    String in,finalstring = "";

    while ((in=br.readLine()) != null){

    finalstring += in+"\n";

    }

    browser.println("Content-Type: text/xml");

    browser.println(finalstring);

    } catch(Exception e) {

    e.printStackTrace();

    }

    }

    }

    • avatar
    • Anthony
    • Mon 13 Mar 2006 05:36 PM

    To say 'To prevent malicious code you can only use Ajax on and within your own website' is incorrect. Of the browsers I use to develop for there are different methods that allow XSS to occur.

    In IE, not sure about 7, if a website is listed in the 'Trusted Sites' the javascript is allowed to perform XSS without user interaction.

    In Firefox there is no such 'Trusted Sites' area to allow XSS to occur. You are however able to sign the javascript and zip it up with the file extension '.jar'. You do need a CA to do this though. Once this is done AJAX calls to other servers are allowed.

    For an example of the signed javascript check out the DWA 6/7 mail templates in Domino these allow XSS. Also the Mozilla site has an article from the good old Netscape DevEdge with more information

    {Link}

    In relation to other browsers I do not use them so I can't comment.

    Regards,

    Anthony

  13. Not sure if anyone is interested in this anymore, but I had a requirement for cross-domain scripting that was "GET"ing data from an https (SSL) webpage. For those that *are* interested, I have stumbled across a solution.

    The solution builds on Jeff Crossett's suggestion of passing a url to a LotusScript agent which means that my solution will only work on wintel - apologies for those on other O/S environments.

    If you use Jeff's code then the Msxml2.ServerXMLHTTP object returns the error:

    "msxml3.dll: The certificate authority is invalid or incorrect"

    The magic line that prevents the above error?

    xmlhttp.setoption(2,13056) ' ignore SSL errors

    So the code you need is:

    'initialise relevant objects, including the string url which is the path to your https website e.g. url = "https://www.blah.com"

    Set xmlhttp = CreateObject("Msxml2.ServerXMLHTTP")

    Call xmlhttp.setoption(2,13056) 'ignore SSL errors

    Call xmlhttp.open("GET", url, False)

    Call xmlhttp.send()

    print xmlhttp.responseText

    Beautiful!!!

  14. Unfortunately, xmlhttp.responseText seems to accept only UTF-8 charset.

    To read RSS, it's not pretty. I prefer the cross-domain proxy solution with JAVA. The data are not modified.

    • avatar
    • Amal
    • Tue 6 Feb 2007 12:58 AM

    When I accessing the Application i am receving below error.

    msxml4.dll error '80072f0d'

    The certificate authority is invalid or incorrect

    /smiles/login.asp, line 70

    In the code we calling

    dim xmlhttp

    set xmlhttp = server.Createobject("MSXML2.ServerXMLHTTP.4.0")

    dim xmlDOM

    set xmlDOM = server.Createobject("MSXML2.ServerXMLHTTP.4.0")

    with xmlhttp

    .Open "GET", txturl, false .responseXML.async = false

    .send xmlDOM

    • avatar
    • amir
    • Tue 11 Dec 2007 03:48 AM

    i should use proxy for using xmlhttp when i set proxy i get this error

    Public member 'setProxy' on

    type 'IXMLHTTPRequest' not found.

    any body could help me about it ?

    • avatar
    • Mark K
    • Thu 11 Jun 2009 08:17 AM

    In reply to Roger Arundell...

    just a quick thankyou for your "msxml3.dll: The certificate authority is invalid or incorrect".

    I'd been searching for a COM object that would do this for a few days. You've saved me significant effort as the next choice was re-code in java - not something I wanted to do on a last-minute change.

    Thanks again,

    M

  15. THANK YOU Roger - you save my day !!!

    • avatar
    • swathi
    • Mon 27 Jun 2011 05:24 AM

    Hi ,

    I have s:file upload tag in my jsp.and one sx:autocompleter tag.

    if i change the element in sx:autocompleter the ajax to work.

    But the s:file tag is preventing not to work ajax properly.

    Can you give me some idea.Pls…..

    Im trying this for past one week…..

    Thanks in advance.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Fri 10 Mar 2006

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content