URLs in GitLab
Overview
GitLab supports multiple deployment configurations that affect how URLs are generated and resolved. Using hardcoded or absolute URLs can break functionality in these scenarios:
- Relative URL installations - GitLab deployments with a path prefix, for example,
https://example.com/gitlab/. - Geo deployments - Primary and secondary sites with different URLs
- Organization scoped routes - Dynamic URL structures based on organization context
To ensure URLs work correctly across all deployment configurations follow the below guidelines.
General guidelines
- Use Rails as the single source of truth for generating URLs. If you need a URL on the frontend, generate it in Rails and pass it to the frontend.
- Use relative URLs for internal application links. Use absolute URLs only when:
- Generating links for emails.
- Constructing URLs for external services.
- Building clone or download URLs that must work outside the web interface.
Backend guidelines
Path and URL helpers
Use Rails path and URL helpers to generate URLs.
- Use
*_pathhelpers for all internal application links. - Use
*_urlhelpers only for links that need to be consumed outside of the application, such as:- Links for emails.
- URLs for external services.
- Clone or download URLs that must work outside the web interface.
# Correct - Relative path
redirect_to project_path(@project)
# Incorrect - Absolute URL
redirect_to project_url(@project)Frontend guidelines
JavaScript and Vue
Do not hardcode or construct URLs in JavaScript or Vue. Generate URLs in Rails and pass them to the frontend through data attributes, GraphQL queries, or REST APIs.
// Incorrect - Do not construct URLs on the frontend
const endpoint = `${gon.relative_url_root}/${projectPath}/-/refs`;For correct alternatives, see the following sections.
JavaScript path helpers
We use the js-routes to generate JavaScript path helpers that mirror the backend path helpers. These helpers are generated when starting GDK and can be viewed in the app/assets/javascripts/lib/utils/path_helpers directory. Path helpers support relative URL installations which is globally configured in app/assets/javascripts/behaviors/configure_path_helpers.js.
Finding the correct path helper
The easiest way to find the correct path helper is to search through app/assets/javascripts/lib/utils/path_helpers directory for a substring of the path you need. For example if you need /<project path>/-/snippets/new search for /-/snippets/new until you find the helper that accepts the project path as a parameter.
Path helpers are organized by where they are defined in Rails. For example routes defined in config/routes/project.rb will be available to the frontend in app/assets/javascripts/lib/utils/path_helpers/project.js. This also applies to EE specific path helpers. For example a route defined in ee/config/routes/project.rb will be available to the frontend in ee/app/assets/javascripts/lib/utils/path_helpers/project.js.
For more complicated cases you can find routes for a specific controller by running bin/rails routes -c name_of_controller --expanded. For example if you wanted to see the routes for project snippets you could run bin/rails routes -c projects/snippets --expanded. This would output:
--[ Route 6 ]--------------------------------------------------------------------------------------------------------------
Prefix | new_snippet
Verb | GET
URI | /-/snippets/new(.:format)
Controller#Action | snippets#new
Source Location | /config/routes/snippets.rb:3The JavaScript path helper is the Prefix in camelCase with suffix Path. In the above example it will be newSnippetPath. The Source Location indicates which file the path helper will be in. In the above example it would be in app/assets/javascripts/lib/utils/path_helpers/snippets.js
app/assets/javascripts/lib/utils/path_helpers/*.js should be generated when starting GitLab Development Kit. If the path helpers are not generated or you are getting errors due to them being out of date, you can manually generate the path helpers by running bundle exec rake gitlab:js:routes. Similarly you can clear the cache and restart GDK with yarn clean && gdk restart.
Project path helpers
To improve usability and match Rails functionality in config/routes.rb#L368 project path helpers use a shorthand name and argument. Instead of newNamespaceProjectSnippetPath that accepts namespacePath and projectPath separately it is newProjectSnippetPath that accepts one projectFullPath argument. See example in using path helpers.
Using path helpers
<script>
import { GlLink } from '@gitlab/ui';
import { newProjectSnippetPath } from '~/lib/utils/path_helpers/project';
import { newSnippetPath } from '~/lib/utils/path_helpers/snippets';
export default {
components: {
GlLink
},
props: {
project: {
type: Object,
required: true,
}
},
methods: {
newSnippetPath,
newProjectSnippetPath,
}
};
</script>
<template>
<div>
<gl-link :href="newSnippetPath()">{{ __('New snippet') }}</gl-link>
<gl-link :href="newProjectSnippetPath(project.fullPath)">{{ __('New project snippet') }}</gl-link>
</div>
</template>REST API path helpers
JavaScript path helpers are not generated for REST API paths, such as /api/:version/groups/:id. Use the reusable pattern for REST API paths and utilities in app/assets/javascripts/rest_api.js.
Passing URLs with data attributes
While this approach is still acceptable, using path helpers is preferred.
Pass URLs from Rails to the frontend by using data-* attributes. For example:
#js-my-app{ data: { base_path: project_iteration_cadences_path(project) } }const initMyApp = () => {
const el = document.getElementById('js-my-app');
if (!el) return false;
const { basePath } = el.dataset
}GraphQL queries
Avoid using webUrl fields. Instead, use the webPath or other relative URL field, for
example, adminEditPath. If the webPath field does not exist on that GraphQL type, add
it. Be careful of compatibility across updates
when you add new GraphQL fields.
REST API
Avoid using web_url fields. Instead, use web_path or other relative URL fields, for
example, admin_edit_path. If web_path does not exist on the REST API endpoint, add it.
Be careful of compatibility across updates
when you add new fields to REST API endpoints.
Vue router
For the correct way to configure Vue Router, see Vue Router.
HAML templates
Use *_path helpers instead of *_url helpers:
-# Correct - Relative URL
= link_to _('Dashboard'), dashboard_projects_path
-# Incorrect - Absolute URL
= link_to _('Dashboard'), dashboard_projects_urlLinking to help pages
For guidance on how to link to help pages, see linking to /help.