Commit graph

65 commits

Author SHA1 Message Date
bpirkle
90494183bb REST: add restbase compat error handling mode
In order to replace certain /api/rest_v1 endpoints, we
need to have something in MediaWiki that generates a compatible
responser. The MediaWiki REST API error format does not match
RESTbase. So the easiest approach seemed to be to
add a compatibility mode, triggered using the x-restbase-compat
header. This can be set via the gateway when rerouting the request.

Bug: T374136
Change-Id: I73934940d367be52941bd27861c248ab5bcfb5d2
2024-09-16 18:09:12 -05:00
Ebrahim Byagowi
fab78547ad Add namespace to the root classes of ObjectCache
And deprecated aliases for the the no namespaced classes.

ReplicatedBagOStuff that already is deprecated isn't moved.

Bug: T353458
Change-Id: Ie01962517e5b53e59b9721e9996d4f1ea95abb51
2024-07-10 00:14:54 +03:30
daniel
79c61e80dc REST: Make module definition files more like OpenAPI specs
This splits RouteFileModule into two classes, ExtraRoutesModule and
SpecBasedModule.

ExtraRoutesModule has no module prefix and supports
only "flat" route definition files and additional routes from
extension.json.

SpecBasedModule represents a single module defined in a definition
file similar to an OpenAPI spec. The idea is that a full OpenAPI spec
can be generated by filling in any missing information based on
information provided by the Handler implementation. In particular, the
definition of parameters and request body schemas will be generated.

A JSON schema for the new file format is added under docs/rest/.

Support for the intermediate format introduced in Iebcde4645d4 is
removed. It was not included in a release and was not being used outside
core tests.

Bug: T366837
Change-Id: I4ce306b0997f80b78a3d901e38bbfa8445bed604
2024-06-24 16:42:59 +02:00
jenkins-bot
11b1907cfc Merge "Use real type hints for services etc. in includes/Rest/" 2024-06-11 23:01:04 +00:00
Bartosz Dziewoński
2bd7bc5cc8 Use real type hints for services etc. in includes/Rest/
Mostly used find-and-replace:

Find:
/\*[\*\s]+@var (I?[A-Z](\w+)(?:Interface)?)[\s\*]+/\s*(private|protected|public) (\$[a-z]\w+;\n)((?=\s*/\*[\*\s]+@var (I?[A-Z](\w+)(?:Interface)?))\n|)
Replace with:
\3 \1 \4

More could be done, but to keep this patch reasonably sized, I only
changed the most obvious and unambiguously correct cases.

In some cases, I also removed redundant doc comments on the
constructor, and re-ordered the properties to match the constructor.

Change-Id: Ifa710fdf4d8d44a2d7244798b787a1b2a58c35a7
2024-06-11 22:40:44 +02:00
Wendy Quarshie
e7fd78aed1 Migrate MediaWiki.rest_api to statslib
Bug: T359364
Change-Id: I3646140ee8e16800c43f37958fc4b6ff00edcad6
2024-06-11 18:13:21 +00:00
daniel
44a3221dc9 REST: fix handling for root path
This fixes the handling for the .../rest.php and .../rest.php/ paths.
The handling for the first case (no "/" at the end) is hard-coded to
redirect to the second case (with a "/") at the end. The second case
can then be handled by a regular route definition.

Change-Id: I9782b17e524f96d7dff4a8e2524fce4ed0940379
2024-05-28 10:29:56 +02:00
jenkins-bot
f3d376dc44 Merge "REST: support rest.php when another RestPath is configured." 2024-05-24 03:47:24 +00:00
daniel
bccbae4345 REST: support rest.php when another RestPath is configured.
When a "pretty" RestPath is configured for outside requests, we still
need the "ugly" path to work for backwards compatibility and internal
requests.

For example, the REST API could be available through /api/ as
well as /w/rest.php. This is equivalent to supporting page views
at /wiki/ as well as /w/index.php.

We can already set RestPath to /api, but then requests to /w/rest.php would fail. We need a way to support both at once.

Change-Id: I9ff8e7345e88b1a4235b6870ec04a87527ed271f
2024-05-22 08:34:30 +00:00
daniel
68dc4845b5 REST: fix metrics keys
In Iebcde4645d472d2 I broke the way we generate metrics keys from
endpoint paths. Instead of using the declared paths with placeholders,
we were recording the actual paths, resulting in an explosion of metrics
keys.

This moves metrics logging from Router into Module, where the declared
path is available. This patch also introduces regression tests for the
issue.

Bug: T365111
Change-Id: I2c9ddfe6e28aaecd313356894f17033e2db59073
2024-05-21 17:34:59 +00:00
daniel
91a1741787 Introduce Modules into the REST framework
Modules group together endpoints by a shared prefix. The idea is that each module has its own version and can generated self-contained self-documentation. This allows clients to have clear expectations about the endpoints of each module, no matter what wiki they are accessing. So far, each wiki may be exposing a different set of endpoints, with no way to provide a spec that describes that set of endpoints in a way that would be consistent across wikis and stable over time.

Bug: T362480
Change-Id: Iebcde4645d472d27eee5a30adb6eee12cc7d046b
2024-05-08 16:12:30 +02:00
jenkins-bot
1d66c7fcd0 Merge "REST: Split latency metrics by status code" 2024-04-19 03:00:43 +00:00
daniel
a654fd529c REST: Split latency metrics by status code
Currently, all latency measurments for non-error responses are conflated
into a single value for each endpoint. It would however be useful to be
able to count and time different non-error cases, such as
normalization redirects, wiki redirects, not-modified responses, etc.

NOTE: This will break some Grafana graphs, particularly on the REST API
dashboard: https://grafana.wikimedia.org/d/2pCoanoVk/mw-rest-api
Change-Id: If687be44e964ad5d90fbd4d67e54e6b5d5986fca
2024-04-19 02:05:42 +00:00
daniel
23e0b606bd REST: allow redirects to be defined without specifying a handler
Make the Router class know about redirect definitions, so it is no
necessary to explcitly specify the RedirectHandler.

Bug: T361840
Change-Id: I2f3bce5b426639f1c4ecf55a6c003794019acd14
2024-04-17 18:27:31 +02:00
Wendy Quarshie
2ef78ee34b Improve error localization in REST handlers
BUg: T358745
Change-Id: Icb804560c827ee3e5df56d9d8d9565b8157fa9e1
2024-04-02 16:49:40 +00:00
daniel
a89d6c571f REST: ignore request body on GET requests
GET requests SHOULD NOT have a body. However, there seem to be quite a
few clients that send one anyway. Let's ignore it for now.

The next step would be to check if the body is empty, and fail if it
isn't.

Bug: T359509
Change-Id: I1c1b9de37e8e3b9e8c4500c0477e40c0a44db32d
2024-03-07 15:30:06 +01:00
daniel
b4fd232f86 REST: allow lower-case method names
Bug: T359306
Change-Id: I660813cbd033e3d399c0d79f4714ef9854e013f3
2024-03-06 13:15:17 +01:00
Wendy Quarshie
f4de463f88 Rest router should provide parsed body data to handler.
bug: T358557
Change-Id: I41e81f1166a09a4409319cced20a76dc08c6869e
2024-03-04 12:54:02 +00:00
jenkins-bot
04decb07b8 Merge "Rest: Fix unspecific type hints in REST handler/validators" 2024-02-16 19:32:45 +00:00
thiemowmde
baaf65938f Rest: Fix unspecific type hints in REST handler/validators
Change-Id: I1b002b4dbd4a8ca90aad977029dcc97e5b3fe766
2024-02-16 09:49:27 +01:00
Daniel Kinzler
b73cc87dd1 Re-apply "REST: Emit swagger spec"
This reverts commit 890558f1fa.
This restores Id584208d9b67d877606a0add1d71c9b1784cdb1b with some fixes.

Bug: T323786
Bug: T352742
Change-Id: Ib31c451ddd75b06c95a544c8a3d2a64b32264126
2023-12-06 11:20:11 +01:00
Urbanecm
890558f1fa Revert "REST: Emit swagger spec"
This reverts commit bb4b5c5f87.

Reason for revert: patch breaks CI

Bug: T352742
Change-Id: Iaf57bad945f5cbd01508a513f0d219ec4b510ce8
2023-12-05 10:37:48 +00:00
daniel
bb4b5c5f87 REST: Emit swagger spec
This is only enabled in development mode for now.
It's intended as a baseline for further development,
the feature is not ready for production.

Bug: T323786
Change-Id: Id584208d9b67d877606a0add1d71c9b1784cdb1b
Co-authored-by: Atieno <pnjira@wikimedia.org>
2023-12-04 16:28:32 +03:00
daniel
b57ec34e2b REST: support relative redirects
Make HTTP redirects returned by the REST API use relative
URLs in the Location header. This ensures interoperability with the WMF
service mesh, avoiding issues with internal services trying to resolve
redirects by accessing the canonical external URLs.

Note that relative URLs are allowed in the Location header per RFC 7231,
while the obsolete RFC 2616 required it to be absolute.

Bug: T349001
Change-Id: Ibb38c30eb66aaed14ab3ad01ffc42c348a0d07c8
2023-10-19 16:46:38 +00:00
Aaron Schulz
29bab859fc profiler: Add ProfilingContext class
Use this class to track the entry point and handler used for requests,
making it available for use in profiling, stats, and logging code.

This makes it possible for periodic and/or shutdown profiling callbacks
to know the basic action handler that applies to the request (if any).
Metric names can easily include this string along with MW_ENTRY_POINT
to create per-action profiling dashboards.

This info cannot otherwise be acquired from things like excimer stack
traces since the router and handler classes do not appear in the stack
during PRESEND deferred updates and variations like ApiMain/SpecialPage
"inclusion mode" would have to be detected somehow.

Bug: T330810
Change-Id: Icca5a7a343faeeb18652994c96752acb61a61fd1
2023-03-23 00:08:49 +00:00
Gergő Tisza
939639114b
Rest: Handle exceptions during handler creation
Change-Id: Ia5e31a875161a07b0d4de7ae0eaf6e78e6e86a27
2023-01-22 12:27:37 -08:00
Daniel Kinzler
f2e9d5108d REST: collect metrics on endpoint access
This is a modified version of Ie282bc5b5f5df0bbd6a40c8362ba73fcbbf36c2e
which was reverted in 5c7cca8776.

Bug: T321969
Change-Id: I566d54a473aa51c4cdaada21a49d63c0624aab93
2023-01-12 14:50:58 +00:00
Daniel Kinzler
5c7cca8776 Revert "REST: collect metrics on endpoint access"
This reverts commit d32c260ed0.

Reason for revert: Timo has reservations, I'll submit an updated version later.

Change-Id: I71d4d61a879fda4dccfc105127446cfedde75a7b
2022-12-12 20:05:06 +00:00
daniel
d32c260ed0 REST: collect metrics on endpoint access
This collects metrics on how often each endpoint is hit, and with which
code it responds.

Change-Id: Ie282bc5b5f5df0bbd6a40c8362ba73fcbbf36c2e
2022-12-06 12:46:01 +01:00
daniel
d70fbfc691 REST: introduce applyCacheControl()
This adds applyCacheControl() to the Handler base class.
REST handlers can override this method to apply cache control to the
response.

Change-Id: Ib31b91a0048dbc57fbcadfec6533e672c1567509
2022-11-21 01:22:34 +00:00
daniel
ef9889433f ParsoidHandler: optionally use private URLs for redirects
The ParsoidHanlder base class is used by the Transform endpoint in core,
which should redirect to core's public /page and /revision endpoints,
using URLs based on the CanonicalServer setting.

It is also used by the Page and Transform endpoints in the parsoid
extension, which need to redirect to private endpoints, using URLs based
on the InternalServer setting.

This patch allows that distinction to be made while using the standard
mechanism for determining route URLs provided by the REST framework. So
far, we had a work-around in place that duplicated that logic.

Bug: T311867
Depends-On: I85ac2f2a8626989e111265869ff301fc72dfaa15
Change-Id: I8e154ded4b93b1e7201fc302a968bd88211666bc
2022-07-21 20:02:37 +00:00
daniel
2f8736f1d3 REST: introduce getPrivateRouteUrl
We need a way to determine the URL of routes that are not public,
and should be using $wgInternalServer rather than $wgCanonicalServer.

This patch also refactors some test code to make changes to the
constructor of the Router class less painful.

Bug: T311867
Change-Id: If1878365d019434bb862c643c2350b63479c9844
2022-07-14 13:12:35 +00:00
Bill Pirkle
7295100773 Allow REST API handlers to require csrf-safe session providers
Bug: T305043
Depends-On: Ic7c1b19b86e8a151e2d42aaec00ef0e89db77f08
Change-Id: Ic6bd48b400ecd839ef99b518ef955781470cd05c
2022-05-20 16:52:54 +00:00
Aryeh Gregor
7b4b0135b9 Use str_starts_with/str_ends_with
All the other ways of doing it were ridiculous and much harder to read,
and usually required repeating the needle expression (to get its
length). I found these occurrences by grepping for various expressions,
but I undoubtedly missed some.

I didn't try replacing the many instances of strpos(...) === 0 with
str_starts_with(...), because I think they're readable enough as-is
(although less efficient). Likewise I didn't try porting strpos(...) !==
false to str_contains(...). For case-insensitive comparisons, Tim
Starling requested that we stick with substr_compare() because it's more
efficient than calling strtolower().

On PHP < 8 these functions will be included with a polyfill via
vendor/autoload.php. This is included at the beginning of
includes/AutoLoader.php, so if our autoloader has been included the
polyfill will be available. This means it should be safe to call these
functions from any code that would not be usable without our autoloader.

Three uses that Tim Starling identified as being performance-sensitive
have been split out to a separate commit for porting after the switch to
PHP 8.

Change-Id: I113a8d052b6845852c15969a2f0e6fbbe3e9f8d9
2022-05-02 10:59:58 +03:00
Alexander Vorwerk
9b09bf3112 Use updated ObjectFactory namespace
Depends-On: I99c5e5664d2401c36a9890f148eba7c25e6e8324
Depends-On: I48ab818b2965da14af15ef370aa83ad9455badd9
Depends-On: I018371e4b77911e56152ca7b2df734afc73f58a5
Change-Id: I04ebdb52102f6191d49a9cc70b1f98308299e72f
2022-03-09 23:04:51 +00:00
Thiemo Kreuz
b4c63c64ae Remove some more comments that literally repeat the code
Nothing to learn from these.

You can find a longer explanation in the comments in I93751e6.

Change-Id: I195aae70fc282b58be5b18160783f27d38605d15
2021-12-09 19:01:36 +01:00
daniel
13acba25a0 REST: gracefully handle all exceptions.
ResponseFactory::createFromException already had support for arbitrary
exceptions, but Router was so far only using it for HttpExceptions,
leaving other kinds of exceptions uncaught.

In addition to catching all exceptions and generating an appropriate
JSON response for them, this patch introduces the ErrorReporter
interface, with an MWErrorReporter implementation which calls
MWExceptionHandler::rollbackMasterChangesAndLog(). This is how uncaught
errors are handled for requests coming in via api.php, so it seems
appropriate to use the same approach for requests coming in via
rest.php.

Bug: T285984
Change-Id: I0605a7693821ef58fac80ab67f51a742556a37fd
2021-11-02 20:33:13 +01:00
libraryupgrader
5357695270 build: Updating dependencies
composer:
* mediawiki/mediawiki-codesniffer: 36.0.0 → 37.0.0
  The following sniffs now pass and were enabled:
  * Generic.ControlStructures.InlineControlStructure
  * MediaWiki.PHPUnit.AssertCount.NotUsed

npm:
* svgo: 2.3.0 → 2.3.1
  * https://npmjs.com/advisories/1754 (CVE-2021-33587)

Change-Id: I2a9bbee2fecbf7259876d335f565ece4b3622426
2021-07-22 03:36:05 +00:00
DannyS712
4939ef070d Router::__construct() put one parameter per line
Makes it a bit easier to read and to add new parameters

Change-Id: Ic4b6cae382b0e33c2ca3947e9fc92e64fb792408
2021-07-10 03:50:10 +00:00
Petr Pchelko
22c47c4edd Rest: inject Authority into Handler
Bug: T239753
Change-Id: Iddde137c5a86786357d67458f28fe3e4d6e98710
2021-01-21 15:09:34 -06:00
DannyS712
6a03737104 Update for object-factory v.3
Bug: T267074
Change-Id: Iff9b46c9e78e87d32c8f75d26b284ce01bccb63d
2020-11-17 06:20:23 +00:00
Petr Pchelko
c1d5cbe561 Introduce CompoundAuthorizer to pass multiple authorizers
Change-Id: Icacad6fe95400e1ec9817fae0f9aa6edfe717b43
2020-09-22 00:25:38 +00:00
David Barratt
c36b320454
Handle CORS preflight request and prevent anon users from unsafe methods
Creates an OPTIONS handler that handles any OPTIONS requests that are
not already handled by a handler. CORS has no mechanism to ensure the
user is authenticated, so the Router will reject cross-origin requests
from anon users.

This change allows authenticated users to make cross-origin
requests if they authenticate with OAuth or if
$wgRestAllowCrossOriginCookieAuth is enabled.

Bug: T232176
Bug: T262712
Change-Id: I128b4bdbec4f6bea35142153c951fd7b79617106
2020-09-21 19:29:40 -04:00
Tim Starling
693286d8a6 Make the HookContainer parameter to Rest\Router be required
Depends-On: I21d8eb8b45442e1f6e8ee3a9c9f969f11aabe372
Change-Id: Ie8462d0fa88bb094a8a5820d4dff22ff1077aa1c
2020-09-18 08:14:15 +10:00
daniel
7717db62e1 REST /user/{name}/contribs
Bug: T235073
Change-Id: Ia262d055185c20142629d0824e4ba14a5e5fa9d3
2020-07-09 12:34:52 -07:00
Nikki Nikkhoui
14260d3955 HandlerTestTrait::getRouteUrl behaving differently than Router::getRouteUrl
In HandlerTestTrait::getRouteUrl when a query param had a null value,
the query was not being appended to the url at all. Whereas, in
Router::getRouteUrl a null value would still append on the query key.
HandlerTestTrait::getRouteUrl will now append on query params, even if the value
is null. Additionally, Router::getRouteUrl() can accept path params.

Bug: T255582
Change-Id: I3610f6252f2f0e7ec95ca346a6bdcd774e5260f8
2020-06-16 12:08:07 -07:00
Tim Starling
68c433bd23 Hooks::run() call site migration
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.

General principles:
* Use DI if it is already used. We're not changing the way state is
  managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
  is a service, it's a more generic interface, it is the only
  thing that provides isRegistered() which is needed in some cases,
  and a HookRunner can be efficiently constructed from it
  (confirmed by benchmark). Because HookContainer is needed
  for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
  SpecialPage and ApiBase have getHookContainer() and getHookRunner()
  methods in the base class, and classes that extend that base class
  are not expected to know or care where the base class gets its
  HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
  getHookRunner() methods, getting them from the global service
  container. The point of this is to ease migration to DI by ensuring
  that call sites ask their local friendly base class rather than
  getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
  methods did not seem warranted, there is a private HookRunner property
  which is accessed directly. Very rarely (two cases), there is a
  protected property, for consistency with code that conventionally
  assumes protected=private, but in cases where the class might actually
  be overridden, a protected accessor is preferred over a protected
  property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
  global code. In a few cases it was used for objects with broken
  construction schemes, out of horror or laziness.

Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore

Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router

setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine

Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
2020-05-30 14:23:28 +00:00
daniel
65342f8353 Define POST handler for /page/: create page
NOTE: once this is merged, also merge Ie7b47e6868cc on the OAuth repo,
to fix unit tests after a breaking change to Router's constructor
signature.

Bug: T230842
Change-Id: I8f5b92918a58e44a4f2d8c78d234d9f64c2d06bf
2020-03-25 20:49:20 +01:00
Brad Jorsch
724e1782db Add RestStructureTest
This tests validity of parameter definitions for the MW REST API, like
ApiStructureTest does for the Action API.

Bug: T243437
Change-Id: Iac9ca951d00573be6efe00cc07478c3581c84588
2020-02-04 20:30:10 +00:00
James D. Forrester
4f2d1efdda Coding style: Auto-fix MediaWiki.Classes.UnsortedUseStatements.UnsortedUse
Change-Id: I94a0ae83c65e8ee419bbd1ae1e86ab21ed4d8210
2020-01-10 09:32:25 -08:00