Navigation Handlers ‐ Customizing URL Behavior - ben-vargas/servicenow-wiki GitHub Wiki

This article explains how to use Navigation Handlers in ServiceNow to manipulate URLs and redirect users based on specific criteria. Navigation Handlers are a powerful but often overlooked feature that allows you to customize the user experience by controlling how users access records within the platform.

What are Navigation Handlers?

Navigation Handlers provide a mechanism to intercept a URL request before the corresponding page is rendered. They allow you to examine the incoming request, modify the URL, and ultimately redirect the user to a different page if needed. This is useful for various scenarios, such as directing users to specific views, controlling access based on user roles, or implementing custom navigation flows.

Accessing Navigation Handlers:

You can access Navigation Handlers by navigating to sys_navigator.list in the navigation filter on the left side of your instance.

Key Fields on Navigation Handler Records:

Each Navigation Handler record has the following fields:

  • Table: Specifies the table for which the Navigation Handler should be triggered.
  • Class: This field is not currently used and can be ignored.
  • Script: The JavaScript code that defines the logic for manipulating the URL.

How Navigation Handlers Work:

When a user attempts to access a ServiceNow record (e.g., sc_request.do?sys_id=xxxx), the system checks for any matching Navigation Handlers based on the target table. If a match is found, the associated script executes. The script can:

  1. Inspect: Examine the URL using the g_uri object and the request parameters using the g_request object.
  2. Modify: Modify the URL using the g_uri object.
  3. Redirect: Return the modified URL via the answer variable. If the answer variable is not set, no redirect will occur and the user will load the original record requested.

Default Navigation Handler Example:

The most common use case for Navigation Handlers is the default script used on the sc_request table. This script redirects Self-Service users (or users without roles) to the "Order Status" page when they try to access a Request record directly.

Here's the default script:

(function() {
    var view = g_request.getParameter('sysparm_view');

    if (!view && !gs.getUser().hasRoles())
        view = 'ess';

    if (view == 'ess' || view == 'checkout') {
        var checkOutForm = gs.getProperty('glide.sc.checkout.form', 'com.glideapp.servicecatalog_checkout_view');
        if (checkOutForm == 'com.glideapp.servicecatalog_checkout_view') {
            var realID = g_uri.get('sys_id');
            g_uri.set('sysparm_sys_id', realID);
            answer = g_uri.toString('com.glideapp.servicecatalog_checkout_view.do');
        }
    }
})();

Explanation:

  • g_request.getParameter('sysparm_view'): Retrieves the value of the sysparm_view parameter from the URL. This parameter is often used to specify a specific view of the record.
  • !view && !gs.getUser().hasRoles(): Checks if the view is not specified and if the user does not have any roles, meaning they are considered an end user.
  • view == 'ess' || view == 'checkout': Checks if the view is set to Self-Service (ess) or checkout.
  • gs.getProperty('glide.sc.checkout.form', 'com.glideapp.servicecatalog_checkout_view'): Gets the configured checkout form from system properties, defaulting to the Service Catalog Checkout View.
  • g_uri.get('sys_id'): Retrieves the sys_id parameter from the original URL.
  • g_uri.set('sysparm_sys_id', realID): Sets the sysparm_sys_id parameter in the g_uri to the retrieved sys_id.
  • g_uri.toString('com.glideapp.servicecatalog_checkout_view.do'): Generates a new URL to the "Order Status" page, using the specified view.
  • answer = ...: Assigning a value to the answer variable redirects the user to this URL.

Key Objects: g_uri and g_request

Navigation Handler scripts have access to two key objects:

  • g_uri: This object represents the target URL the user is trying to access. It provides methods to get, set, and modify various parts of the URL, and create new URLs.
  • g_request: This object provides access to the HTTP request parameters passed when accessing the URL.

g_uri Object Methods:

Method Description
g_uri.action() Gets the action part of the URL.
g_uri.addIgnoreParam() Adds parameters to ignore when setting the URL.
g_uri.class() Gets the class part of the URL.
g_uri.deleteMatchingParameter() Deletes the URL parameter using a regular expression.
g_uri.deleteParmameter() Deletes a parameter from the URL.
g_uri.equals() Checks if two URL objects are equal.
g_uri.fileFromPath() Returns the file name from the path.
g_uri.get(parameter) Gets the value of a specific parameter from the URL.
g_uri.getAction() Gets the action part of the URL
g_uri.getClass() Gets the class part of the URL.
g_uri.getFileFromPath() Gets the file from the path of the URL.
g_uri.getMap() Returns the map of parameters in the URL.
g_uri.getPath() Gets the path part of the URL
g_uri.hashCode() Generates a hash code for the URL object.
g_uri.isSetAsDefault() Checks if the URL is set to default.
g_uri.map() Returns the parameters of the URL in a map object
g_uri.notify() Wakes up a single thread waiting on this object's monitor.
g_uri.notifyAll() Wakes up all threads waiting on this object's monitor.
g_uri.path() Returns the path of the URL.
g_uri.set(parameter, value) Sets a parameter in the URL.
g_uri.setAbsoluteURI() Sets the absolute URL.
g_uri.setAction() Sets the action of the URL
g_uri.setAsDefault() Sets the URL as the default
g_uri.setFilter() Sets the filter parameter on the URL.
g_uri.setParameter() Sets a parameter in the URL.
g_uri.setRelatedQuery() Sets the related query parameter on the URL.
g_uri.toString() Converts the g_uri object to a string, optionally appending a view to the URL.
g_uri.wait() Causes the current thread to wait.

g_request Object Methods:

Method Description
g_request.asyncStarted() Checks if asynchronous processing has started.
g_request.asyncSupported() Checks if asynchronous processing is supported.
g_request.authType() Gets the authentication type.
g_request.contentLength() Gets the content length.
g_request.contextPath() Gets the context path.
g_request.cookies() Gets the cookies in the request.
g_request.dispatcherType() Gets the dispatcher type.
g_request.equals() Checks if two request objects are equal.
g_request.getAsyncContext() Gets the asynchronous context.
g_request.getAttribute() Gets a specific attribute.
g_request.getAttributeNames() Gets the names of all attributes.
g_request.getAuthType() Gets the authentication type.
g_request.getCharacterEncoding() Gets the character encoding.
g_request.getContentLength() Gets the content length.
g_request.getContentType() Gets the content type.
g_request.getCookies() Gets the cookies in the request.
g_request.getDispatcherType() Gets the dispatcher type.
g_request.getHeader() Gets a header from the request using the header's name
g_request.getHeaderNames() Gets the names of all headers.
g_request.getInputStream() Gets the input stream.
g_request.getIntHeader() Gets an integer header from the request.
g_request.getLocalAddr() Gets the local address.
g_request.getLocale() Gets the locale.
g_request.getLocales() Gets the locales supported by the request
g_request.getLocalName() Gets the local name.
g_request.getMethod() Gets the HTTP method.
g_request.getOriginalParameterMap() Gets the original parameters from the request.
g_request.getParameterMap() Gets the map of parameters in the request.
g_request.getParameterNames() Gets the names of all parameters.
g_request.getParameterValues() Gets the values of the parameters.
g_request.getPart() Gets a specific multi part message
g_request.getParts() Gets a list of all multi part messages
g_request.getPathInfo() Gets the path info from the request.
g_request.getPathTranslated() Gets the translated path.
g_request.getProtocol() Gets the protocol.
g_request.getRealPath() Gets the real path.
g_request.getRemoteAddr() Gets the remote address.
g_request.getRemoteUser() Gets the remote user.
g_request.getRequestDispatcher() Gets the request dispatcher.
g_request.getRequestedSessionId() Gets the requested session id.
g_request.getRequestURI() Gets the request URI.
g_request.getRequestURL() Gets the request URL.
g_request.getScheme() Gets the scheme.
g_request.getServletPath() Gets the servlet path.
g_request.getSession() Gets the session.
g_request.getSiteID() Gets the site ID.
g_request.getSiteName() Gets the site name.
g_request.getUserPrincipal() Gets the user principal.
g_request.headerNames() Returns an iterator over the header names of the request.
g_request.inputStream() Returns an input stream to read the request body
g_request.isAsyncStarted() Checks if asynchronous processing has started.
g_request.isAsyncSupported() Checks if asynchronous processing is supported.
g_request.isPublic() Checks if the request is public.
g_request.isRequestedSessionIdFromCookie() Checks if the session id is from the cookie
g_request.isRequestedSessionIdFromUrl() Checks if the session id is from the URL
g_request.isRequestedSessionIdFromURL() Checks if the session id is from the URL
g_request.isRequestedSessionIdValid() Checks if the session id is valid
g_request.isSecure() Checks if the request is secure.
g_request.isVirtual() Checks if the request is virtual.
g_request.localAddr() Gets the local address.
g_request.locale() Gets the locale.
g_request.locales() Returns the locales that are supported for this request
g_request.login() Logs in a user.
g_request.logout() Logs out a user.
g_request.method() Returns the HTTP method used in this request
g_request.notify() Wakes up a single thread waiting on this object's monitor.
g_request.notifyAll() Wakes up all threads waiting on this object's monitor.
g_request.originalParameterMap() Returns the original set of parameter values when the request was made
g_request.parameterMap() Returns a map of the current set of parameters in the request.
g_request.parameterNames() Returns a list of parameter names.
g_request.parts() Returns all of the multi part messages in the request.
g_request.pathInfo() Returns the path information of this request.
g_request.pathTranslated() Returns the translated path of this request
g_request.protocol() Gets the protocol used in the request
g_request.queryString() Returns the query string of this request.
g_request.reader() Returns a reader that can be used to read the request body
g_request.remoteAddr() Returns the remote IP address used by the client making the request
g_request.remoteHost() Returns the remote host making the request
g_request.remotePort() Returns the remote port being used in the request
g_request.removeAttribute() Removes the attribute in the request using its name
g_request.requestedSessionId() Returns the requested session id for the request
g_request.requestedSessionIdFromCookie() Checks to see if the session ID was requested using a cookie
g_request.requestedSessionIdFromURL() Checks to see if the session ID was requested using the url
g_request.requestedSessionIdValid() Checks to see if the requested session ID is still valid
g_request.requestURI() Returns the URI requested by the client
g_request.requestURL() Returns the URL requested by the client
g_request.scheme() Returns the scheme used in this request.
g_request.secure() Checks to see if this request was made over a secure connection
g_request.serverPort() Returns the port number of the server
g_request.servletPath() Returns the servlet path used by this request
g_request.setAttribute() Allows you to set an attribute on the request using name and value
g_request.setCharacterEncoding() Allows you to set the character encoding on this request.
g_request.setParameter() Allows you to set a parameter on the request.
g_request.siteID() Returns the ID of the site the client is accessing
g_request.startAsync() Returns the asynchronous context and begins asynchronous processing.
g_request.toString() Returns the string representation of this request.
g_request.updateSessionLastAccessedTime() Updates the session time.
g_request.userPrincipal() Returns the principal for this user
g_request.virtual() Checks to see if this request is considered virtual
g_request.wait() Causes the current thread to wait.

Use Cases:

  • Custom Views: Redirect users based on their roles or groups to specific views of the record, enhancing usability.
  • External Access: Redirect external users trying to access a native ServiceNow record to a custom self-service page, which is important for security.
  • URL Rewriting: Create custom URLs that are easier to share while still pointing to the correct location.
  • Conditional Navigation: Implement complex navigation flows based on the state of the record or user-specific criteria.

How to Implement:

  1. Navigate: Go to sys_navigator.list to view Navigation Handlers.
  2. Create or Modify: Create a new Navigation Handler or modify an existing one for a specific table.
  3. Add Script: Add your custom JavaScript logic to the script field.
  4. Test: Test your handler thoroughly by accessing records on the target table.

Best Practices:

  • Keep it Simple: Keep your navigation handler script as simple as possible for better performance and maintainability.
  • Logging: Log important actions using gs.info or gs.debug to help with troubleshooting.
  • Specificity: Make your handlers as specific as possible by using both table and conditions so they do not trigger unnecessarily.
  • Testing: Thoroughly test in a development environment before deploying to production.
  • Avoid infinite loops: Make sure that you avoid creating an infinite loop, which is very easy to do when manipulating the URL in your script.

Security Considerations:

  • Be cautious with redirecting users.
  • Ensure proper security access controls are in place.
  • Do not expose sensitive data in your logic or your redirection URLs.

Conclusion:

Navigation Handlers are a valuable tool for customizing navigation in ServiceNow. By using g_uri and g_request objects you can implement complex redirection rules based on specific parameters, improving the user experience and ensuring that users are always directed to the correct location. Remember to test all changes thoroughly in a non-production environment before deploying to production.