215 * |
223 * |
216 * @see WP_REST_Server::dispatch() |
224 * @see WP_REST_Server::dispatch() |
217 * |
225 * |
218 * @param string $path Optional. The request route. If not set, `$_SERVER['PATH_INFO']` will be used. |
226 * @param string $path Optional. The request route. If not set, `$_SERVER['PATH_INFO']` will be used. |
219 * Default null. |
227 * Default null. |
220 * @return false|null Null if not served and a HEAD request, false otherwise. |
228 * @return null|false Null if not served and a HEAD request, false otherwise. |
221 */ |
229 */ |
222 public function serve_request( $path = null ) { |
230 public function serve_request( $path = null ) { |
223 $content_type = isset( $_GET['_jsonp'] ) ? 'application/javascript' : 'application/json'; |
231 $content_type = isset( $_GET['_jsonp'] ) ? 'application/javascript' : 'application/json'; |
224 $this->send_header( 'Content-Type', $content_type . '; charset=' . get_option( 'blog_charset' ) ); |
232 $this->send_header( 'Content-Type', $content_type . '; charset=' . get_option( 'blog_charset' ) ); |
225 $this->send_header( 'X-Robots-Tag', 'noindex' ); |
233 $this->send_header( 'X-Robots-Tag', 'noindex' ); |
233 * Mitigate possible JSONP Flash attacks. |
241 * Mitigate possible JSONP Flash attacks. |
234 * |
242 * |
235 * https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ |
243 * https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ |
236 */ |
244 */ |
237 $this->send_header( 'X-Content-Type-Options', 'nosniff' ); |
245 $this->send_header( 'X-Content-Type-Options', 'nosniff' ); |
238 $this->send_header( 'Access-Control-Expose-Headers', 'X-WP-Total, X-WP-TotalPages' ); |
246 $expose_headers = array( 'X-WP-Total', 'X-WP-TotalPages', 'Link' ); |
239 $this->send_header( 'Access-Control-Allow-Headers', 'Authorization, Content-Type' ); |
247 |
|
248 /** |
|
249 * Filters the list of response headers that are exposed to CORS requests. |
|
250 * |
|
251 * @since 5.5.0 |
|
252 * |
|
253 * @param string[] $expose_headers The list of headers to expose. |
|
254 */ |
|
255 $expose_headers = apply_filters( 'rest_exposed_cors_headers', $expose_headers ); |
|
256 |
|
257 $this->send_header( 'Access-Control-Expose-Headers', implode( ', ', $expose_headers ) ); |
|
258 |
|
259 $allow_headers = array( |
|
260 'Authorization', |
|
261 'X-WP-Nonce', |
|
262 'Content-Disposition', |
|
263 'Content-MD5', |
|
264 'Content-Type', |
|
265 ); |
|
266 |
|
267 /** |
|
268 * Filters the list of request headers that are allowed for CORS requests. |
|
269 * |
|
270 * The allowed headers are passed to the browser to specify which |
|
271 * headers can be passed to the REST API. By default, we allow the |
|
272 * Content-* headers needed to upload files to the media endpoints. |
|
273 * As well as the Authorization and Nonce headers for allowing authentication. |
|
274 * |
|
275 * @since 5.5.0 |
|
276 * |
|
277 * @param string[] $allow_headers The list of headers to allow. |
|
278 */ |
|
279 $allow_headers = apply_filters( 'rest_allowed_cors_headers', $allow_headers ); |
|
280 |
|
281 $this->send_header( 'Access-Control-Allow-Headers', implode( ', ', $allow_headers ) ); |
240 |
282 |
241 /** |
283 /** |
242 * Send nocache headers on authenticated requests. |
284 * Send nocache headers on authenticated requests. |
243 * |
285 * |
244 * @since 4.4.0 |
286 * @since 4.4.0 |
258 |
300 |
259 /** |
301 /** |
260 * Filters whether the REST API is enabled. |
302 * Filters whether the REST API is enabled. |
261 * |
303 * |
262 * @since 4.4.0 |
304 * @since 4.4.0 |
263 * @deprecated 4.7.0 Use the rest_authentication_errors filter to restrict access to the API |
305 * @deprecated 4.7.0 Use the {@see 'rest_authentication_errors'} filter to |
|
306 * restrict access to the API. |
264 * |
307 * |
265 * @param bool $rest_enabled Whether the REST API is enabled. Default true. |
308 * @param bool $rest_enabled Whether the REST API is enabled. Default true. |
266 */ |
309 */ |
267 apply_filters_deprecated( |
310 apply_filters_deprecated( |
268 'rest_enabled', |
311 'rest_enabled', |
269 array( true ), |
312 array( true ), |
270 '4.7.0', |
313 '4.7.0', |
271 'rest_authentication_errors', |
314 'rest_authentication_errors', |
272 __( 'The REST API can no longer be completely disabled, the rest_authentication_errors filter can be used to restrict access to the API, instead.' ) |
315 sprintf( |
|
316 /* translators: %s: rest_authentication_errors */ |
|
317 __( 'The REST API can no longer be completely disabled, the %s filter can be used to restrict access to the API, instead.' ), |
|
318 'rest_authentication_errors' |
|
319 ) |
273 ); |
320 ); |
274 |
321 |
275 /** |
322 /** |
276 * Filters whether jsonp is enabled. |
323 * Filters whether jsonp is enabled. |
277 * |
324 * |
308 |
355 |
309 $request->set_query_params( wp_unslash( $_GET ) ); |
356 $request->set_query_params( wp_unslash( $_GET ) ); |
310 $request->set_body_params( wp_unslash( $_POST ) ); |
357 $request->set_body_params( wp_unslash( $_POST ) ); |
311 $request->set_file_params( $_FILES ); |
358 $request->set_file_params( $_FILES ); |
312 $request->set_headers( $this->get_headers( wp_unslash( $_SERVER ) ) ); |
359 $request->set_headers( $this->get_headers( wp_unslash( $_SERVER ) ) ); |
313 $request->set_body( $this->get_raw_data() ); |
360 $request->set_body( self::get_raw_data() ); |
314 |
361 |
315 /* |
362 /* |
316 * HTTP method override for clients that can't use PUT/PATCH/DELETE. First, we check |
363 * HTTP method override for clients that can't use PUT/PATCH/DELETE. First, we check |
317 * $_GET['_method']. If that is not set, we check for the HTTP_X_HTTP_METHOD_OVERRIDE |
364 * $_GET['_method']. If that is not set, we check for the HTTP_X_HTTP_METHOD_OVERRIDE |
318 * header. |
365 * header. |
399 * @param WP_REST_Server $this Server instance. |
447 * @param WP_REST_Server $this Server instance. |
400 * @param WP_REST_Request $request Request used to generate the response. |
448 * @param WP_REST_Request $request Request used to generate the response. |
401 */ |
449 */ |
402 $result = apply_filters( 'rest_pre_echo_response', $result, $this, $request ); |
450 $result = apply_filters( 'rest_pre_echo_response', $result, $this, $request ); |
403 |
451 |
|
452 // The 204 response shouldn't have a body. |
|
453 if ( 204 === $code || null === $result ) { |
|
454 return null; |
|
455 } |
|
456 |
404 $result = wp_json_encode( $result ); |
457 $result = wp_json_encode( $result ); |
405 |
458 |
406 $json_error_message = $this->get_json_last_error(); |
459 $json_error_message = $this->get_json_last_error(); |
|
460 |
407 if ( $json_error_message ) { |
461 if ( $json_error_message ) { |
408 $json_error_obj = new WP_Error( 'rest_encode_error', $json_error_message, array( 'status' => 500 ) ); |
462 $json_error_obj = new WP_Error( |
409 $result = $this->error_to_response( $json_error_obj ); |
463 'rest_encode_error', |
410 $result = wp_json_encode( $result->data[0] ); |
464 $json_error_message, |
|
465 array( 'status' => 500 ) |
|
466 ); |
|
467 |
|
468 $result = $this->error_to_response( $json_error_obj ); |
|
469 $result = wp_json_encode( $result->data[0] ); |
411 } |
470 } |
412 |
471 |
413 if ( $jsonp_callback ) { |
472 if ( $jsonp_callback ) { |
414 // Prepend '/**/' to mitigate possible JSONP Flash attacks. |
473 // Prepend '/**/' to mitigate possible JSONP Flash attacks. |
415 // https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ |
474 // https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ |
416 echo '/**/' . $jsonp_callback . '(' . $result . ')'; |
475 echo '/**/' . $jsonp_callback . '(' . $result . ')'; |
417 } else { |
476 } else { |
418 echo $result; |
477 echo $result; |
419 } |
478 } |
420 } |
479 } |
|
480 |
421 return null; |
481 return null; |
422 } |
482 } |
423 |
483 |
424 /** |
484 /** |
425 * Converts a response to data to send. |
485 * Converts a response to data to send. |
426 * |
486 * |
427 * @since 4.4.0 |
487 * @since 4.4.0 |
|
488 * @since 5.4.0 The $embed parameter can now contain a list of link relations to include. |
428 * |
489 * |
429 * @param WP_REST_Response $response Response object. |
490 * @param WP_REST_Response $response Response object. |
430 * @param bool $embed Whether links should be embedded. |
491 * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. |
431 * @return array { |
492 * @return array { |
432 * Data with sub-requests embedded. |
493 * Data with sub-requests embedded. |
433 * |
494 * |
434 * @type array [$_links] Links. |
495 * @type array $_links Links. |
435 * @type array [$_embedded] Embeddeds. |
496 * @type array $_embedded Embeddeds. |
436 * } |
497 * } |
437 */ |
498 */ |
438 public function response_to_data( $response, $embed ) { |
499 public function response_to_data( $response, $embed ) { |
439 $data = $response->get_data(); |
500 $data = $response->get_data(); |
440 $links = $this->get_compact_response_links( $response ); |
501 $links = self::get_compact_response_links( $response ); |
441 |
502 |
442 if ( ! empty( $links ) ) { |
503 if ( ! empty( $links ) ) { |
443 // Convert links to part of the data. |
504 // Convert links to part of the data. |
444 $data['_links'] = $links; |
505 $data['_links'] = $links; |
445 } |
506 } |
|
507 |
446 if ( $embed ) { |
508 if ( $embed ) { |
|
509 $this->embed_cache = array(); |
447 // Determine if this is a numeric array. |
510 // Determine if this is a numeric array. |
448 if ( wp_is_numeric_array( $data ) ) { |
511 if ( wp_is_numeric_array( $data ) ) { |
449 $data = array_map( array( $this, 'embed_links' ), $data ); |
512 foreach ( $data as $key => $item ) { |
|
513 $data[ $key ] = $this->embed_links( $item, $embed ); |
|
514 } |
450 } else { |
515 } else { |
451 $data = $this->embed_links( $data ); |
516 $data = $this->embed_links( $data, $embed ); |
452 } |
517 } |
|
518 $this->embed_cache = array(); |
453 } |
519 } |
454 |
520 |
455 return $data; |
521 return $data; |
456 } |
522 } |
457 |
523 |
540 |
607 |
541 /** |
608 /** |
542 * Embeds the links from the data into the request. |
609 * Embeds the links from the data into the request. |
543 * |
610 * |
544 * @since 4.4.0 |
611 * @since 4.4.0 |
545 * |
612 * @since 5.4.0 The $embed parameter can now contain a list of link relations to include. |
546 * @param array $data Data from the request. |
613 * |
|
614 * @param array $data Data from the request. |
|
615 * @param bool|string[] $embed Whether to embed all links or a filtered list of link relations. |
547 * @return array { |
616 * @return array { |
548 * Data with sub-requests embedded. |
617 * Data with sub-requests embedded. |
549 * |
618 * |
550 * @type array [$_links] Links. |
619 * @type array $_links Links. |
551 * @type array [$_embedded] Embeddeds. |
620 * @type array $_embedded Embeddeds. |
552 * } |
621 * } |
553 */ |
622 */ |
554 protected function embed_links( $data ) { |
623 protected function embed_links( $data, $embed = true ) { |
555 if ( empty( $data['_links'] ) ) { |
624 if ( empty( $data['_links'] ) ) { |
556 return $data; |
625 return $data; |
557 } |
626 } |
558 |
627 |
559 $embedded = array(); |
628 $embedded = array(); |
560 |
629 |
561 foreach ( $data['_links'] as $rel => $links ) { |
630 foreach ( $data['_links'] as $rel => $links ) { |
562 // Ignore links to self, for obvious reasons. |
631 // If a list of relations was specified, and the link relation |
563 if ( 'self' === $rel ) { |
632 // is not in the list of allowed relations, don't process the link. |
|
633 if ( is_array( $embed ) && ! in_array( $rel, $embed, true ) ) { |
564 continue; |
634 continue; |
565 } |
635 } |
566 |
636 |
567 $embeds = array(); |
637 $embeds = array(); |
568 |
638 |
572 // Ensure we keep the same order. |
642 // Ensure we keep the same order. |
573 $embeds[] = array(); |
643 $embeds[] = array(); |
574 continue; |
644 continue; |
575 } |
645 } |
576 |
646 |
577 // Run through our internal routing and serve. |
647 if ( ! array_key_exists( $item['href'], $this->embed_cache ) ) { |
578 $request = WP_REST_Request::from_url( $item['href'] ); |
648 // Run through our internal routing and serve. |
579 if ( ! $request ) { |
649 $request = WP_REST_Request::from_url( $item['href'] ); |
580 $embeds[] = array(); |
650 if ( ! $request ) { |
581 continue; |
651 $embeds[] = array(); |
582 } |
652 continue; |
583 |
653 } |
584 // Embedded resources get passed context=embed. |
654 |
585 if ( empty( $request['context'] ) ) { |
655 // Embedded resources get passed context=embed. |
586 $request['context'] = 'embed'; |
656 if ( empty( $request['context'] ) ) { |
587 } |
657 $request['context'] = 'embed'; |
588 |
658 } |
589 $response = $this->dispatch( $request ); |
659 |
590 |
660 $response = $this->dispatch( $request ); |
591 /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ |
661 |
592 $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $this, $request ); |
662 /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ |
593 |
663 $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $this, $request ); |
594 $embeds[] = $this->response_to_data( $response, false ); |
664 |
|
665 $this->embed_cache[ $item['href'] ] = $this->response_to_data( $response, false ); |
|
666 } |
|
667 |
|
668 $embeds[] = $this->embed_cache[ $item['href'] ]; |
595 } |
669 } |
596 |
670 |
597 // Determine if any real links were found. |
671 // Determine if any real links were found. |
598 $has_links = count( array_filter( $embeds ) ); |
672 $has_links = count( array_filter( $embeds ) ); |
599 |
673 |
703 * |
777 * |
704 * Note that the path regexes (array keys) must have @ escaped, as this is |
778 * Note that the path regexes (array keys) must have @ escaped, as this is |
705 * used as the delimiter with preg_match() |
779 * used as the delimiter with preg_match() |
706 * |
780 * |
707 * @since 4.4.0 |
781 * @since 4.4.0 |
708 * |
782 * @since 5.4.0 Add $namespace parameter. |
|
783 * |
|
784 * @param string $namespace Optionally, only return routes in the given namespace. |
709 * @return array `'/path/regex' => array( $callback, $bitmask )` or |
785 * @return array `'/path/regex' => array( $callback, $bitmask )` or |
710 * `'/path/regex' => array( array( $callback, $bitmask ), ...)`. |
786 * `'/path/regex' => array( array( $callback, $bitmask ), ...)`. |
711 */ |
787 */ |
712 public function get_routes() { |
788 public function get_routes( $namespace = '' ) { |
|
789 $endpoints = $this->endpoints; |
|
790 |
|
791 if ( $namespace ) { |
|
792 $endpoints = wp_list_filter( $endpoints, array( 'namespace' => $namespace ) ); |
|
793 } |
713 |
794 |
714 /** |
795 /** |
715 * Filters the array of available endpoints. |
796 * Filters the array of available endpoints. |
716 * |
797 * |
717 * @since 4.4.0 |
798 * @since 4.4.0 |
719 * @param array $endpoints The available endpoints. An array of matching regex patterns, each mapped |
800 * @param array $endpoints The available endpoints. An array of matching regex patterns, each mapped |
720 * to an array of callbacks for the endpoint. These take the format |
801 * to an array of callbacks for the endpoint. These take the format |
721 * `'/path/regex' => array( $callback, $bitmask )` or |
802 * `'/path/regex' => array( $callback, $bitmask )` or |
722 * `'/path/regex' => array( array( $callback, $bitmask ). |
803 * `'/path/regex' => array( array( $callback, $bitmask ). |
723 */ |
804 */ |
724 $endpoints = apply_filters( 'rest_endpoints', $this->endpoints ); |
805 $endpoints = apply_filters( 'rest_endpoints', $endpoints ); |
725 |
806 |
726 // Normalise the endpoints. |
807 // Normalise the endpoints. |
727 $defaults = array( |
808 $defaults = array( |
728 'methods' => '', |
809 'methods' => '', |
729 'accept_json' => false, |
810 'accept_json' => false, |
831 } |
912 } |
832 |
913 |
833 $method = $request->get_method(); |
914 $method = $request->get_method(); |
834 $path = $request->get_route(); |
915 $path = $request->get_route(); |
835 |
916 |
836 foreach ( $this->get_routes() as $route => $handlers ) { |
917 $with_namespace = array(); |
|
918 |
|
919 foreach ( $this->get_namespaces() as $namespace ) { |
|
920 if ( 0 === strpos( trailingslashit( ltrim( $path, '/' ) ), $namespace ) ) { |
|
921 $with_namespace[] = $this->get_routes( $namespace ); |
|
922 } |
|
923 } |
|
924 |
|
925 if ( $with_namespace ) { |
|
926 $routes = array_merge( ...$with_namespace ); |
|
927 } else { |
|
928 $routes = $this->get_routes(); |
|
929 } |
|
930 |
|
931 foreach ( $routes as $route => $handlers ) { |
837 $match = preg_match( '@^' . $route . '$@i', $path, $matches ); |
932 $match = preg_match( '@^' . $route . '$@i', $path, $matches ); |
838 |
933 |
839 if ( ! $match ) { |
934 if ( ! $match ) { |
840 continue; |
935 continue; |
841 } |
936 } |
842 |
937 |
843 $args = array(); |
938 $args = array(); |
|
939 |
844 foreach ( $matches as $param => $value ) { |
940 foreach ( $matches as $param => $value ) { |
845 if ( ! is_int( $param ) ) { |
941 if ( ! is_int( $param ) ) { |
846 $args[ $param ] = $value; |
942 $args[ $param ] = $value; |
847 } |
943 } |
848 } |
944 } |
859 if ( empty( $handler['methods'][ $checked_method ] ) ) { |
955 if ( empty( $handler['methods'][ $checked_method ] ) ) { |
860 continue; |
956 continue; |
861 } |
957 } |
862 |
958 |
863 if ( ! is_callable( $callback ) ) { |
959 if ( ! is_callable( $callback ) ) { |
864 $response = new WP_Error( 'rest_invalid_handler', __( 'The handler for the route is invalid' ), array( 'status' => 500 ) ); |
960 $response = new WP_Error( |
|
961 'rest_invalid_handler', |
|
962 __( 'The handler for the route is invalid' ), |
|
963 array( 'status' => 500 ) |
|
964 ); |
865 } |
965 } |
866 |
966 |
867 if ( ! is_wp_error( $response ) ) { |
967 if ( ! is_wp_error( $response ) ) { |
868 // Remove the redundant preg_match argument. |
968 // Remove the redundant preg_match argument. |
869 unset( $args[0] ); |
969 unset( $args[0] ); |
902 * Note that this filter will not be called for requests that |
1002 * Note that this filter will not be called for requests that |
903 * fail to authenticate or match to a registered route. |
1003 * fail to authenticate or match to a registered route. |
904 * |
1004 * |
905 * @since 4.7.0 |
1005 * @since 4.7.0 |
906 * |
1006 * |
907 * @param WP_HTTP_Response|WP_Error $response Result to send to the client. Usually a WP_REST_Response or WP_Error. |
1007 * @param WP_REST_Response|WP_HTTP_Response|WP_Error|mixed $response Result to send to the client. Usually a WP_REST_Response or WP_Error. |
908 * @param array $handler Route handler used for the request. |
1008 * @param array $handler Route handler used for the request. |
909 * @param WP_REST_Request $request Request used to generate the response. |
1009 * @param WP_REST_Request $request Request used to generate the response. |
910 */ |
1010 */ |
911 $response = apply_filters( 'rest_request_before_callbacks', $response, $handler, $request ); |
1011 $response = apply_filters( 'rest_request_before_callbacks', $response, $handler, $request ); |
912 |
1012 |
913 if ( ! is_wp_error( $response ) ) { |
1013 if ( ! is_wp_error( $response ) ) { |
914 // Check permission specified on the route. |
1014 // Check permission specified on the route. |
916 $permission = call_user_func( $handler['permission_callback'], $request ); |
1016 $permission = call_user_func( $handler['permission_callback'], $request ); |
917 |
1017 |
918 if ( is_wp_error( $permission ) ) { |
1018 if ( is_wp_error( $permission ) ) { |
919 $response = $permission; |
1019 $response = $permission; |
920 } elseif ( false === $permission || null === $permission ) { |
1020 } elseif ( false === $permission || null === $permission ) { |
921 $response = new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to do that.' ), array( 'status' => rest_authorization_required_code() ) ); |
1021 $response = new WP_Error( |
|
1022 'rest_forbidden', |
|
1023 __( 'Sorry, you are not allowed to do that.' ), |
|
1024 array( 'status' => rest_authorization_required_code() ) |
|
1025 ); |
922 } |
1026 } |
923 } |
1027 } |
924 } |
1028 } |
925 |
1029 |
926 if ( ! is_wp_error( $response ) ) { |
1030 if ( ! is_wp_error( $response ) ) { |
961 * Note that an endpoint's `permission_callback` can still be |
1065 * Note that an endpoint's `permission_callback` can still be |
962 * called after this filter - see `rest_send_allow_header()`. |
1066 * called after this filter - see `rest_send_allow_header()`. |
963 * |
1067 * |
964 * @since 4.7.0 |
1068 * @since 4.7.0 |
965 * |
1069 * |
966 * @param WP_HTTP_Response|WP_Error $response Result to send to the client. Usually a WP_REST_Response or WP_Error. |
1070 * @param WP_REST_Response|WP_HTTP_Response|WP_Error|mixed $response Result to send to the client. Usually a WP_REST_Response or WP_Error. |
967 * @param array $handler Route handler used for the request. |
1071 * @param array $handler Route handler used for the request. |
968 * @param WP_REST_Request $request Request used to generate the response. |
1072 * @param WP_REST_Request $request Request used to generate the response. |
969 */ |
1073 */ |
970 $response = apply_filters( 'rest_request_after_callbacks', $response, $handler, $request ); |
1074 $response = apply_filters( 'rest_request_after_callbacks', $response, $handler, $request ); |
971 |
1075 |
972 if ( is_wp_error( $response ) ) { |
1076 if ( is_wp_error( $response ) ) { |
973 $response = $this->error_to_response( $response ); |
1077 $response = $this->error_to_response( $response ); |
1067 */ |
1172 */ |
1068 public function get_namespace_index( $request ) { |
1173 public function get_namespace_index( $request ) { |
1069 $namespace = $request['namespace']; |
1174 $namespace = $request['namespace']; |
1070 |
1175 |
1071 if ( ! isset( $this->namespaces[ $namespace ] ) ) { |
1176 if ( ! isset( $this->namespaces[ $namespace ] ) ) { |
1072 return new WP_Error( 'rest_invalid_namespace', __( 'The specified namespace could not be found.' ), array( 'status' => 404 ) ); |
1177 return new WP_Error( |
|
1178 'rest_invalid_namespace', |
|
1179 __( 'The specified namespace could not be found.' ), |
|
1180 array( 'status' => 404 ) |
|
1181 ); |
1073 } |
1182 } |
1074 |
1183 |
1075 $routes = $this->namespaces[ $namespace ]; |
1184 $routes = $this->namespaces[ $namespace ]; |
1076 $endpoints = array_intersect_key( $this->get_routes(), $routes ); |
1185 $endpoints = array_intersect_key( $this->get_routes(), $routes ); |
1077 |
1186 |
1277 * @since 4.8.0 |
1391 * @since 4.8.0 |
1278 * |
1392 * |
1279 * @param string $key Header key. |
1393 * @param string $key Header key. |
1280 */ |
1394 */ |
1281 public function remove_header( $key ) { |
1395 public function remove_header( $key ) { |
1282 if ( function_exists( 'header_remove' ) ) { |
1396 header_remove( $key ); |
1283 // In PHP 5.3+ there is a way to remove an already set header. |
|
1284 header_remove( $key ); |
|
1285 } else { |
|
1286 // In PHP 5.2, send an empty header, but only as a last resort to |
|
1287 // override a header already sent. |
|
1288 foreach ( headers_list() as $header ) { |
|
1289 if ( 0 === stripos( $header, "$key:" ) ) { |
|
1290 $this->send_header( $key, '' ); |
|
1291 break; |
|
1292 } |
|
1293 } |
|
1294 } |
|
1295 } |
1397 } |
1296 |
1398 |
1297 /** |
1399 /** |
1298 * Retrieves the raw request entity (body). |
1400 * Retrieves the raw request entity (body). |
1299 * |
1401 * |
1302 * @global string $HTTP_RAW_POST_DATA Raw post data. |
1404 * @global string $HTTP_RAW_POST_DATA Raw post data. |
1303 * |
1405 * |
1304 * @return string Raw request data. |
1406 * @return string Raw request data. |
1305 */ |
1407 */ |
1306 public static function get_raw_data() { |
1408 public static function get_raw_data() { |
|
1409 // phpcs:disable PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved |
1307 global $HTTP_RAW_POST_DATA; |
1410 global $HTTP_RAW_POST_DATA; |
1308 |
1411 |
1309 /* |
1412 // $HTTP_RAW_POST_DATA was deprecated in PHP 5.6 and removed in PHP 7.0. |
1310 * A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default, |
|
1311 * but we can do it ourself. |
|
1312 */ |
|
1313 if ( ! isset( $HTTP_RAW_POST_DATA ) ) { |
1413 if ( ! isset( $HTTP_RAW_POST_DATA ) ) { |
1314 $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); |
1414 $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); |
1315 } |
1415 } |
1316 |
1416 |
1317 return $HTTP_RAW_POST_DATA; |
1417 return $HTTP_RAW_POST_DATA; |
|
1418 // phpcs:enable |
1318 } |
1419 } |
1319 |
1420 |
1320 /** |
1421 /** |
1321 * Extracts headers from a PHP-style $_SERVER array. |
1422 * Extracts headers from a PHP-style $_SERVER array. |
1322 * |
1423 * |
1336 ); |
1437 ); |
1337 |
1438 |
1338 foreach ( $server as $key => $value ) { |
1439 foreach ( $server as $key => $value ) { |
1339 if ( strpos( $key, 'HTTP_' ) === 0 ) { |
1440 if ( strpos( $key, 'HTTP_' ) === 0 ) { |
1340 $headers[ substr( $key, 5 ) ] = $value; |
1441 $headers[ substr( $key, 5 ) ] = $value; |
|
1442 } elseif ( 'REDIRECT_HTTP_AUTHORIZATION' === $key && empty( $server['HTTP_AUTHORIZATION'] ) ) { |
|
1443 /* |
|
1444 * In some server configurations, the authorization header is passed in this alternate location. |
|
1445 * Since it would not be passed in in both places we do not check for both headers and resolve. |
|
1446 */ |
|
1447 $headers['AUTHORIZATION'] = $value; |
1341 } elseif ( isset( $additional[ $key ] ) ) { |
1448 } elseif ( isset( $additional[ $key ] ) ) { |
1342 $headers[ $key ] = $value; |
1449 $headers[ $key ] = $value; |
1343 } |
1450 } |
1344 } |
1451 } |
1345 |
1452 |