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:
- Inspect: Examine the URL using the
g_uri
object and the request parameters using theg_request
object. - Modify: Modify the URL using the
g_uri
object. - 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 thesysparm_view
parameter from the URL. This parameter is often used to specify a specific view of the record.!view && !gs.getUser().hasRoles()
: Checks if theview
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 thesys_id
parameter from the original URL.g_uri.set('sysparm_sys_id', realID)
: Sets thesysparm_sys_id
parameter in theg_uri
to the retrievedsys_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.
g_uri
and g_request
Key Objects: 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:
- Navigate: Go to
sys_navigator.list
to view Navigation Handlers. - Create or Modify: Create a new Navigation Handler or modify an existing one for a specific table.
- Add Script: Add your custom JavaScript logic to the script field.
- 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
orgs.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.