doc/development/urls_in_gitlab.md
GitLab supports multiple deployment configurations that affect how URLs are generated and resolved. Using hardcoded or absolute URLs can break functionality in these scenarios:
https://example.com/gitlab/.To ensure URLs work correctly across all deployment configurations follow the below guidelines.
Use Rails path and URL helpers to generate URLs.
*_path helpers for all internal application links.*_url helpers only for links that need to be consumed outside of the application, such as:
# Correct - Relative path
redirect_to project_path(@project)
# Incorrect - Absolute URL
redirect_to project_url(@project)
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.
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.
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:3
The 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
[!note]
app/assets/javascripts/lib/utils/path_helpers/*.jsshould 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 runningbundle exec rake gitlab:js:routes. Similarly you can clear the cache and restart GDK withyarn clean && gdk restart.
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.
<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>
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.
[!note] 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
}
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.
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.
For the correct way to configure Vue Router, see Vue Router.
Use *_path helpers instead of *_url helpers:
-# Correct - Relative URL
= link_to _('Dashboard'), dashboard_projects_path
-# Incorrect - Absolute URL
= link_to _('Dashboard'), dashboard_projects_url
For guidance on how to link to help pages, see linking to /help.