Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Office Add-In Development - Malformed GET URL (_host_Info=...)

I am currently developing a MS Word Office Addin using the JavaScript interface provided by Microsoft. I made a test implementation using a Django backend, where everything worked fine.

However for the final product I have to integrate functionality with an existing Java Backend that runs in multiple configurations, which are out of my control. Consisting of Vaadin for the UI and mostly Tomcat (but not always) as a Servlet Container.

I've run into the problem that the IFrame that runs inside Word, appends an unwanted and malformed _host_info to the request URL, that contains un-urlencoded pipe characters. e.g: Tomcat Log:

"GET /myapp/?_host_Info=Word|Win32|16.01|en-US HTTP/1.1" 200 2101

This malformed URL produces the following exception:

java.lang.RuntimeException: Invalid location URI received from client.
... full stack trace at bottom of the post...
Caused by: java.net.URISyntaxException: Illegal character in query at index          45: https://localhost:8443/myapp/?_host_Info=Word|Win32|16.01|en-US

As far as I know, I have no control, on whether or not to append this Parameter to the URL, since in the Manifest File of the Addin I only specify the source URL like below, and the info gets added automatically.

<SourceLocation DefaultValue="https://localhost:8443/myapp/ " />

Checking the Documentation I didn't find this behaviour in there, so i might be missing something. Querying the host info is mentioned in this blog post, but it seems it should not be part of the URL.

  • Is there a way I can stop the Office Add-In from appending: ?_host_Info=Word|Win32|16.01|en-US HTTP/1.1 to the request?

  • If not, is there a correct way to filte/ignore that part of the URL with Tomcat? Since the whole app has been running correctly with my Apache Webserver & Django Backend, where the URL was received too, but it worked.

As for question two, I've already tried to implement a Servlet filter that should remove the parameter in question. But since it relies on the same Java library to parse the URL to look at it, the same exception is thrown.

> May 23, 2016 11:04:51 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [MyUIServlet] in context with path [/word-to-moxis] threw exception [com.vaadin.server.ServiceException: java.lang.RuntimeException: Invalid location URI received from client] with root cause
java.net.URISyntaxException: Illegal character in query at index h(invalidated link because of 10 reputation / two links allowed policy)ttps://localhost:8443/myapp/?_host_Info=Word|Win32|16.01|en-US
    at java.net.URI$Parser.fail(URI.java:2848)
    at java.net.URI$Parser.checkChars(URI.java:3021)
    at java.net.URI$Parser.parseHierarchical(URI.java:3111)
    at java.net.URI$Parser.parse(URI.java:3053)
    at java.net.URI.<init>(URI.java:588)
    at com.vaadin.server.Page.init(Page.java:651)
    at com.vaadin.ui.UI.doInit(UI.java:679)
    at com.vaadin.server.communication.`UIInitHandler`.getBrowserDetailsUI(UIInitHandler.java:214)

Update:

The following Quick & Dirty Hack acts as a workaround of the problem. Still baffled as to why they chose to encode the information that way:

public class AddinServletRequestWrapper extends HttpServletRequestWrapper {

    Map<String, String[]> parameterMap;

    public AddinServletRequestWrapper(HttpServletRequest originalRequest) {
        super(originalRequest);
        parameterMap = new HashMap<String, String[]>(originalRequest.getParameterMap());
        parameterMap.remove("_host_Info");
    }

    @Override
    public String getParameter(String name) {
        // TODO: Improve
        String[] value = parameterMap.get(name);
        if (value == null || value.length == 0)
            return null;
        if(name == "v-loc"){
            return value[0].replace('|', '_');
        }

        return value[0];
    }
}

Update 2/ Feb17:

With more recent Tomcat updates the workaround above no longer suffices. As noted in the comments, the versions 7.0.73, 8.0.39, 8.5.7 have a stricter URL policy. Therefore there is no solution to use the versions of tomcat for hosting office add-ins without additional tooling. I really hope this situation changes soon because such a small, probably useless string can use such problems with deployments.

like image 771
Matthias P. Avatar asked May 23 '16 10:05

Matthias P.


People also ask

Why can't I get add-ins on Microsoft Word?

If an Office add-in isn't showing up in the Office Add-ins list, refresh the list to see all of your add-ins. In Word 2016, Excel 2016, or PowerPoint 2016 click Insert > My Add-ins. In Project 2016, click Project > My Add-ins. Then click Refresh to update the list in the Office Add-ins dialog.

Can't add add-ins in Outlook?

If you don't see the add-ins icon or you're unable to access the list of add-ins, then you'll need to check your add-ins status. To do this in Outlook, click on the File menu, and then click the button to Manage Add-ins (Figure C). Sign into Exchange or Office 365 with your email address and password.


3 Answers

UPDATE: The API is now available for use:

console.log(Office.context.host); //example: Excel

console.log(Office.context.platform); //example: PC, MAC, IOS, null (for stand alone website)

Possible values for host are: Word Excel PowerPoint Outlook OneNote Project Access

Possible values for platform are: PC OfficeOnline Mac iOS Android Universal


We recently removed the query parameters from the URL in light of the issues noted in single page applications. the _host_info_ is no longer appended for add-ins opened in the browser (Office Online).

@Matthias: For this issue, adding office-js tag would be more accurate. I couldn't append given the size limit for tags.

like image 61
Sudhi Ramamurthy Avatar answered Nov 15 '22 08:11

Sudhi Ramamurthy


If you have an apache with mod_rewrite enabled in front of your tomcat, it's possible to add this dirty apache rule to infly reencode the outlook request :

RewriteCond %{QUERY_STRING} (.*)_host_Info=(.*)\|(.*)\|(.*)\|(.*)\|(.*)\|(.*)
RewriteRule ^(.*) "$1?%1_host_Info=%2\%7c%3\%7c%4\%7c%5\%7c%6\%7c%7" [QSD,PT]

I hope this can help

like image 43
Vincent Avatar answered Nov 15 '22 08:11

Vincent


This change of the URL also wreaks havoc in Angular if you are playing with the urlRouteProvider at all. It appears to create a digest loop because it is location changing event to fire inside Angular which exceeds the 10 loop limit of the digest. :(

like image 36
Chris Beiter Avatar answered Nov 15 '22 08:11

Chris Beiter