@@ -39,24 +39,21 @@ Alternative implementation
39
39
--------------------------
40
40
41
41
Instead of trying to map a URL to a view,
42
- we first analyze the canonical project (given from the subdomain),
43
- and based on that we map each part of the URL (parts are the result of splitting the URL on ``/ ``)
44
- to the *current * project.
42
+ we first analyze the root project (given from the subdomain),
43
+ and based on that we map each part of the URL to the *current * project and version.
45
44
46
- This will allow us to re-use this code in our resolver
45
+ This will allow us to re-use this code in our unresolver
47
46
without the need to override the Django's urlconf at runtime,
48
47
or guessing a project only by the structure of its URL.
49
48
50
49
Terminology:
51
50
52
- Canonical project
51
+ Root project
53
52
The project from where the documentation
54
- is served (the parent project of a subproject or translation).
53
+ is served (usually the parent project of a subproject or translation).
55
54
Current project
56
55
The project that owns the current file being served
57
56
(a subproject, a translation, etc).
58
- URL part
59
- The result of splitting the URL on ``/ ``.
60
57
Requested file
61
58
The final path to the file that we need to serve from the current project.
62
59
@@ -66,9 +63,9 @@ Look up process
66
63
Proxito will process all documentation requests from a single *docs serve * view,
67
64
exluding ``/_ `` URLs.
68
65
69
- This view then will process the current URL using the canonical project as follows:
66
+ This view then will process the current URL using the root project as follows:
70
67
71
- - Check if the canonical project has translations
68
+ - Check if the root project has translations
72
69
(the project itself is a translation if isn't a single version project),
73
70
and the first part is a language code and the second is a version.
74
71
@@ -80,7 +77,7 @@ This view then will process the current URL using the canonical project as follo
80
77
81
78
- If the subproject prefix or the alias don't match, we continue.
82
79
- If they match, we try to match the rest of the URL for translations/versions and single versions
83
- (i.e, we don't search for subprojects) and we use the subproject as the new *canonical project *.
80
+ (i.e, we don't search for subprojects) and we use the subproject as the new *root project *.
84
81
85
82
- Check if the project is a single version.
86
83
Here we just try to serve the rest of the URL as the file.
@@ -109,14 +106,14 @@ Doesn't seem useful to do so.
109
106
110
107
So, what we need is have a way to specify a prefix only.
111
108
We would have a prefix used for translations and another one used for subprojects.
112
- These prefixes will be set in the canonical project.
109
+ These prefixes will be set in the root project.
113
110
114
111
The look up order would be as follow:
115
112
116
- - If the canonical project has a custom prefix, and the current URL matches that prefix,
113
+ - If the root project has a custom prefix, and the current URL matches that prefix,
117
114
remove the prefix and follow the translations and single version look up process.
118
115
We exclude subprojects from it, i.e, we don't check for ``{prefix}/projects ``.
119
- - If the canonical project has subprojects and a custom subprojects prefix (``projects `` by default),
116
+ - If the root project has subprojects and a custom subprojects prefix (``projects `` by default),
120
117
and if the current URL matches that prefix,
121
118
and the next part of the URL matches a subproject alias,
122
119
continue with the subproject look up process.
@@ -128,8 +125,8 @@ The next examples are organized in the following way:
128
125
129
126
- First there is a list of the projects involved,
130
127
with their available versions.
131
- - The first project would be the canonical project.
132
- - The other projects will be related to the canonical project
128
+ - The first project would be the root project.
129
+ - The other projects will be related to the root project
133
130
(their relationship is given by their name).
134
131
- Next we will have a table of the requests,
135
132
and their result.
@@ -412,29 +409,32 @@ This is a simplified version of the implementation,
412
409
there are some small optimizations and validations that will be in the
413
410
final implementation.
414
411
412
+ In the final implementation we will be using regular expressions to extract
413
+ the parts from the URL.
414
+
415
415
.. code-block :: python
416
416
417
417
from readthedocs.projects.models import Project
418
-
418
+
419
419
LANGUAGES = {" es" , " en" }
420
-
420
+
421
421
def pop_parts (path , n ):
422
422
if path[0 ] == ' /' :
423
423
path = path[1 :]
424
424
parts = path.split(' /' , maxsplit = n)
425
425
start, end = parts[:n], parts[n:]
426
426
end = end[0 ] if end else ' '
427
427
return start, end
428
-
429
-
428
+
429
+
430
430
def resolve (canonical_project : Project, path : str , check_subprojects = True ):
431
431
prefix = ' /'
432
432
if canonical_project.prefix:
433
433
prefix = canonical_project.prefix
434
434
subproject_prefix = " /projects"
435
435
if canonical_project.subproject_prefix:
436
436
subproject_prefix = canonical_project.subproject_prefix
437
-
437
+
438
438
# Multiversion project.
439
439
if path.startswith(prefix):
440
440
new_path = path.removeprefix(prefix)
@@ -450,7 +450,7 @@ final implementation.
450
450
if version:
451
451
return project, version, new_path
452
452
return project, None , None
453
-
453
+
454
454
# Subprojects.
455
455
if check_subprojects and path.startswith(subproject_prefix):
456
456
new_path = path.removeprefix(subproject_prefix)
@@ -463,7 +463,7 @@ final implementation.
463
463
path = new_path,
464
464
check_subprojects = False ,
465
465
)
466
-
466
+
467
467
# Single project.
468
468
if path.startswith(prefix):
469
469
new_path = path.removeprefix(prefix)
@@ -474,28 +474,28 @@ final implementation.
474
474
if version:
475
475
return canonical_project, version, new_path
476
476
return canonical_project, None , None
477
-
477
+
478
478
return None , None , None
479
-
480
-
479
+
480
+
481
481
def view (canonical_project , path ):
482
482
current_project, version, file = resolve(
483
483
canonical_project = canonical_project,
484
484
path = path,
485
485
)
486
486
if current_project and version:
487
487
return serve(current_project, version, file )
488
-
488
+
489
489
if current_project:
490
490
return serve_404(current_project)
491
-
491
+
492
492
return serve_404(canonical_project)
493
-
494
-
493
+
494
+
495
495
def serve_404 (project , version = None ):
496
496
pass
497
-
498
-
497
+
498
+
499
499
def serve (project , version , file ):
500
500
pass
501
501
@@ -504,8 +504,7 @@ Performance
504
504
~~~~~~~~~~~
505
505
506
506
Performance is mainly driven by the number of database lookups.
507
- There is an additional impact of splitting and joining the paths,
508
- but those are linear operations, and can be optimized to make then constant (i.e. using ``maxsplit=4 ``).
507
+ There is an additional impact performing a regex lookup.
509
508
510
509
- A single version project:
511
510
@@ -546,7 +545,7 @@ Questions
546
545
- robots and sitemap
547
546
- The ``page `` redirect
548
547
549
- I'd say we shouldn't, I can't think of a reason why this should be supported .
548
+ This can be useful for people that proxy us from another path .
550
549
551
550
- Should we use the urlconf from the subproject when processing it?
552
551
This is an URL like ``/projects/subproject/custom/prefix/en/latest/index.html ``.
0 commit comments