/** * REST API: WP_REST_Server class * * @package WordPress * @subpackage REST_API * @since 4.4.0 */ /** * Core class used to implement the WordPress REST API server. * * @since 4.4.0 */ #[AllowDynamicProperties] class WP_REST_Server { /** * Alias for GET transport method. * * @since 4.4.0 * @var string */ const READABLE = 'GET'; /** * Alias for POST transport method. * * @since 4.4.0 * @var string */ const CREATABLE = 'POST'; /** * Alias for POST, PUT, PATCH transport methods together. * * @since 4.4.0 * @var string */ const EDITABLE = 'POST, PUT, PATCH'; /** * Alias for DELETE transport method. * * @since 4.4.0 * @var string */ const DELETABLE = 'DELETE'; /** * Alias for GET, POST, PUT, PATCH & DELETE transport methods together. * * @since 4.4.0 * @var string */ const ALLMETHODS = 'GET, POST, PUT, PATCH, DELETE'; /** * Namespaces registered to the server. * * @since 4.4.0 * @var array */ protected $namespaces = array(); /** * Endpoints registered to the server. * * @since 4.4.0 * @var array */ protected $endpoints = array(); /** * Options defined for the routes. * * @since 4.4.0 * @var array */ protected $route_options = array(); /** * Caches embedded requests. * * @since 5.4.0 * @var array */ protected $embed_cache = array(); /** * Stores request objects that are currently being handled. * * @since 6.5.0 * @var array */ protected $dispatching_requests = array(); /** * Instantiates the REST server. * * @since 4.4.0 */ public function __construct() { $this->endpoints = array( // Meta endpoints. '/' => array( 'callback' => array( $this, 'get_index' ), 'methods' => 'GET', 'args' => array( 'context' => array( 'default' => 'view', ), ), ), '/batch/v1' => array( 'callback' => array( $this, 'serve_batch_request_v1' ), 'methods' => 'POST', 'args' => array( 'validation' => array( 'type' => 'string', 'enum' => array( 'require-all-validate', 'normal' ), 'default' => 'normal', ), 'requests' => array( 'required' => true, 'type' => 'array', 'maxItems' => $this->get_max_batch_size(), 'items' => array( 'type' => 'object', 'properties' => array( 'method' => array( 'type' => 'string', 'enum' => array( 'POST', 'PUT', 'PATCH', 'DELETE' ), 'default' => 'POST', ), 'path' => array( 'type' => 'string', 'required' => true, ), 'body' => array( 'type' => 'object', 'properties' => array(), 'additionalProperties' => true, ), 'headers' => array( 'type' => 'object', 'properties' => array(), 'additionalProperties' => array( 'type' => array( 'string', 'array' ), 'items' => array( 'type' => 'string', ), ), ), ), ), ), ), ), ); } /** * Checks the authentication headers if supplied. * * @since 4.4.0 * * @return WP_Error|null|true WP_Error if authentication error occurred, null if authentication * method wasn't used, true if authentication succeeded. */ public function check_authentication() { /** * Filters REST API authentication errors. * * This is used to pass a WP_Error from an authentication method back to * the API. * * Authentication methods should check first if they're being used, as * multiple authentication methods can be enabled on a site (cookies, * HTTP basic auth, OAuth). If the authentication method hooked in is * not actually being attempted, null should be returned to indicate * another authentication method should check instead. Similarly, * callbacks should ensure the value is `null` before checking for * errors. * * A WP_Error instance can be returned if an error occurs, and this should * match the format used by API methods internally (that is, the `status` * data should be used). A callback can return `true` to indicate that * the authentication method was used, and it succeeded. * * @since 4.4.0 * * @param WP_Error|null|true $errors WP_Error if authentication error occurred, null if authentication * method wasn't used, true if authentication succeeded. */ return apply_filters( 'rest_authentication_errors', null ); } /** * Converts an error to a response object. * * This iterates over all error codes and messages to change it into a flat * array. This enables simpler client behavior, as it is represented as a * list in JSON rather than an object/map. * * @since 4.4.0 * @since 5.7.0 Converted to a wrapper of {@see rest_convert_error_to_response()}. * * @param WP_Error $error WP_Error instance. * @return WP_REST_Response List of associative arrays with code and message keys. */ protected function error_to_response( $error ) { return rest_convert_error_to_response( $error ); } /** * Retrieves an appropriate error representation in JSON. * * Note: This should only be used in WP_REST_Server::serve_request(), as it * cannot handle WP_Error internally. All callbacks and other internal methods * should instead return a WP_Error with the data set to an array that includes * a 'status' key, with the value being the HTTP status to send. * * @since 4.4.0 * * @param string $code WP_Error-style code. * @param string $message Human-readable message. * @param int|null $status Optional. HTTP status code to send. Default null. * @return string JSON representation of the error. */ protected function json_error( $code, $message, $status = null ) { if ( $status ) { $this->set_status( $status ); } $error = compact( 'code', 'message' ); return wp_json_encode( $error ); } /** * Gets the encoding options passed to {@see wp_json_encode}. * * @since 6.1.0 * * @param \WP_REST_Request $request The current request object. * * @return int The JSON encode options. */ protected function get_json_encode_options( WP_REST_Request $request ) { $options = 0; if ( $request->has_param( '_pretty' ) ) { $options |= JSON_PRETTY_PRINT; } /** * Filters the JSON encoding options used to send the REST API response. * * @since 6.1.0 * * @param int $options JSON encoding options {@see json_encode()}. * @param WP_REST_Request $request Current request object. */ return apply_filters( 'rest_json_encode_options', $options, $request ); } /** * Handles serving a REST API request. * * Matches the current server URI to a route and runs the first matching * callback then outputs a JSON representation of the returned value. * * @since 4.4.0 * * @see WP_REST_Server::dispatch() * * @global WP_User $current_user The currently authenticated user. * * @param string|null $path Optional. The request route. If not set, `$_SERVER['PATH_INFO']` will be used. * Default null. * @return null|false Null if not served and a HEAD request, false otherwise. */ public function serve_request( $path = null ) { // Refuse to start a fresh top-level REST cycle while another dispatch // is already in flight. Internal sub-requests must use dispatch(). if ( $this->is_dispatching() ) { return false; } /* @var WP_User|null $current_user */ global $current_user; if ( $current_user instanceof WP_User && ! $current_user->exists() ) { /* * If there is no current user authenticated via other means, clear * the cached lack of user, so that an authenticate check can set it * properly. * * This is done because for authentications such as Application * Passwords, we don't want it to be accepted unless the current HTTP * request is a REST API request, which can't always be identified early * enough in evaluation. */ $current_user = null; } /** * Filters whether JSONP is enabled for the REST API. * * @since 4.4.0 * * @param bool $jsonp_enabled Whether JSONP is enabled. Default true. */ $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true ); $jsonp_callback = false; if ( isset( $_GET['_jsonp'] ) ) { $jsonp_callback = $_GET['_jsonp']; } $content_type = ( $jsonp_callback && $jsonp_enabled ) ? 'application/javascript' : 'application/json'; $this->send_header( 'Content-Type', $content_type . '; charset=' . get_option( 'blog_charset' ) ); $this->send_header( 'X-Robots-Tag', 'noindex' ); $api_root = get_rest_url(); if ( ! empty( $api_root ) ) { $this->send_header( 'Link', '<' . sanitize_url( $api_root ) . '>; rel="https://api.w.org/"' ); } /* * Mitigate possible JSONP Flash attacks. * * https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ */ $this->send_header( 'X-Content-Type-Options', 'nosniff' ); /** * Filters whether the REST API is enabled. * * @since 4.4.0 * @deprecated 4.7.0 Use the {@see 'rest_authentication_errors'} filter to * restrict access to the REST API. * * @param bool $rest_enabled Whether the REST API is enabled. Default true. */ apply_filters_deprecated( 'rest_enabled', array( true ), '4.7.0', 'rest_authentication_errors', sprintf( /* translators: %s: rest_authentication_errors */ __( 'The REST API can no longer be completely disabled, the %s filter can be used to restrict access to the API, instead.' ), 'rest_authentication_errors' ) ); if ( $jsonp_callback ) { if ( ! $jsonp_enabled ) { echo $this->json_error( 'rest_callback_disabled', __( 'JSONP support is disabled on this site.' ), 400 ); return false; } if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) { echo $this->json_error( 'rest_callback_invalid', __( 'Invalid JSONP callback function.' ), 400 ); return false; } } if ( empty( $path ) ) { $path = $_SERVER['PATH_INFO'] ?? '/'; } $request = new WP_REST_Request( $_SERVER['REQUEST_METHOD'], $path ); $request->set_query_params( wp_unslash( $_GET ) ); $request->set_body_params( wp_unslash( $_POST ) ); $request->set_file_params( $_FILES ); $request->set_headers( $this->get_headers( wp_unslash( $_SERVER ) ) ); $request->set_body( self::get_raw_data() ); /* * HTTP method override for clients that can't use PUT/PATCH/DELETE. First, we check * $_GET['_method']. If that is not set, we check for the HTTP_X_HTTP_METHOD_OVERRIDE * header. */ $method_overridden = false; if ( isset( $_GET['_method'] ) ) { $request->set_method( $_GET['_method'] ); } elseif ( isset( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) ) { $request->set_method( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ); $method_overridden = true; } $expose_headers = array( 'X-WP-Total', 'X-WP-TotalPages', 'Link' ); /** * Filters the list of response headers that are exposed to REST API CORS requests. * * @since 5.5.0 * @since 6.3.0 The `$request` parameter was added. * * @param string[] $expose_headers The list of response headers to expose. * @param WP_REST_Request $request The request in context. */ $expose_headers = apply_filters( 'rest_exposed_cors_headers', $expose_headers, $request ); $this->send_header( 'Access-Control-Expose-Headers', implode( ', ', $expose_headers ) ); $allow_headers = array( 'Authorization', 'X-WP-Nonce', 'Content-Disposition', 'Content-MD5', 'Content-Type', ); /** * Filters the list of request headers that are allowed for REST API CORS requests. * * The allowed headers are passed to the browser to specify which * headers can be passed to the REST API. By default, we allow the * Content-* headers needed to upload files to the media endpoints. * As well as the Authorization and Nonce headers for allowing authentication. * * @since 5.5.0 * @since 6.3.0 The `$request` parameter was added. * * @param string[] $allow_headers The list of request headers to allow. * @param WP_REST_Request $request The request in context. */ $allow_headers = apply_filters( 'rest_allowed_cors_headers', $allow_headers, $request ); $this->send_header( 'Access-Control-Allow-Headers', implode( ', ', $allow_headers ) ); $result = $this->check_authentication(); if ( ! is_wp_error( $result ) ) { $result = $this->dispatch( $request ); } // Normalize to either WP_Error or WP_REST_Response... $result = rest_ensure_response( $result ); // ...then convert WP_Error across. if ( is_wp_error( $result ) ) { $result = $this->error_to_response( $result ); } /** * Filters the REST API response. * * Allows modification of the response before returning. * * @since 4.4.0 * @since 4.5.0 Applied to embedded responses. * * @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`. * @param WP_REST_Server $server Server instance. * @param WP_REST_Request $request Request used to generate the response. */ $result = apply_filters( 'rest_post_dispatch', rest_ensure_response( $result ), $this, $request ); // Wrap the response in an envelope if asked for. if ( isset( $_GET['_envelope'] ) ) { $embed = isset( $_GET['_embed'] ) ? rest_parse_embed_param( $_GET['_embed'] ) : false; $result = $this->envelope_response( $result, $embed ); } // Send extra data from response objects. $headers = $result->get_headers(); $this->send_headers( $headers ); $code = $result->get_status(); $this->set_status( $code ); /** * Filters whether to send no-cache headers on a REST API request. * * @since 4.4.0 * @since 6.3.2 Moved the block to catch the filter added on rest_cookie_check_errors() from wp-includes/rest-api.php. * * @param bool $rest_send_nocache_headers Whether to send no-cache headers. */ $send_no_cache_headers = apply_filters( 'rest_send_nocache_headers', is_user_logged_in() ); /* * Send no-cache headers if $send_no_cache_headers is true, * OR if the HTTP_X_HTTP_METHOD_OVERRIDE is used but resulted a 4xx response code. */ if ( $send_no_cache_headers || ( true === $method_overridden && str_starts_with( $code, '4' ) ) ) { foreach ( wp_get_nocache_headers() as $header => $header_value ) { if ( empty( $header_value ) ) { $this->remove_header( $header ); } else { $this->send_header( $header, $header_value ); } } } /** * Filters whether the REST API request has already been served. * * Allow sending the request manually - by returning true, the API result * will not be sent to the client. * * @since 4.4.0 * * @param bool $served Whether the request has already been served. Default false. * @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`. * @param WP_REST_Request $request Request used to generate the response. * @param WP_REST_Server $server Server instance. */ $served = apply_filters( 'rest_pre_serve_request', false, $result, $request, $this ); if ( ! $served ) { if ( 'HEAD' === $request->get_method() ) { return null; } // Embed links inside the request. $embed = isset( $_GET['_embed'] ) ? rest_parse_embed_param( $_GET['_embed'] ) : false; $result = $this->response_to_data( $result, $embed ); /** * Filters the REST API response. * * Allows modification of the response data after inserting * embedded data (if any) and before echoing the response data. * * @since 4.8.1 * * @param array $result Response data to send to the client. * @param WP_REST_Server $server Server instance. * @param WP_REST_Request $request Request used to generate the response. */ $result = apply_filters( 'rest_pre_echo_response', $result, $this, $request ); // The 204 response shouldn't have a body. if ( 204 === $code || null === $result ) { return null; } $result = wp_json_encode( $result, $this->get_json_encode_options( $request ) ); $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { $this->set_status( 500 ); $json_error_obj = new WP_Error( 'rest_encode_error', $json_error_message, array( 'status' => 500 ) ); $result = $this->error_to_response( $json_error_obj ); $result = wp_json_encode( $result->data, $this->get_json_encode_options( $request ) ); } if ( $jsonp_callback ) { // Prepend '/**/' to mitigate possible JSONP Flash attacks. // https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/ echo '/**/' . $jsonp_callback . '(' . $result . ')'; } else { echo $result; } } return null; } /** * Converts a response to data to send. * * @since 4.4.0 * @since 5.4.0 The `$embed` parameter can now contain a list of link relations to include. * * @param WP_REST_Response $response Response object. * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. * @return array { * Data with sub-requests embedded. * * @type array $_links Links. * @type array $_embedded Embedded objects. * } */ public function response_to_data( $response, $embed ) { $data = $response->get_data(); $links = self::get_compact_response_links( $response ); if ( ! empty( $links ) ) { // Convert links to part of the data. $data['_links'] = $links; } if ( $embed ) { $this->embed_cache = array(); // Determine if this is a numeric array. if ( wp_is_numeric_array( $data ) ) { foreach ( $data as $key => $item ) { $data[ $key ] = $this->embed_links( $item, $embed ); } } else { $data = $this->embed_links( $data, $embed ); } $this->embed_cache = array(); } return $data; } /** * Retrieves links from a response. * * Extracts the links from a response into a structured hash, suitable for * direct output. * * @since 4.4.0 * * @param WP_REST_Response $response Response to extract links from. * @return array Map of link relation to list of link hashes. */ public static function get_response_links( $response ) { $links = $response->get_links(); if ( empty( $links ) ) { return array(); } // Convert links to part of the data. $data = array(); foreach ( $links as $rel => $items ) { $data[ $rel ] = array(); foreach ( $items as $item ) { $attributes = $item['attributes']; $attributes['href'] = $item['href']; if ( 'self' !== $rel ) { $data[ $rel ][] = $attributes; continue; } $target_hints = self::get_target_hints_for_link( $attributes ); if ( $target_hints ) { $attributes['targetHints'] = $target_hints; } $data[ $rel ][] = $attributes; } } return $data; } /** * Gets the target hints for a REST API Link. * * @since 6.7.0 * * @param array $link The link to get target hints for. * @return array|null */ protected static function get_target_hints_for_link( $link ) { // Prefer targetHints that were specifically designated by the developer. if ( isset( $link['targetHints']['allow'] ) ) { return null; } $request = WP_REST_Request::from_url( $link['href'] ); if ( ! $request ) { return null; } $server = rest_get_server(); $match = $server->match_request_to_handler( $request ); if ( is_wp_error( $match ) ) { return null; } if ( is_wp_error( $request->has_valid_params() ) ) { return null; } if ( is_wp_error( $request->sanitize_params() ) ) { return null; } $target_hints = array(); $response = new WP_REST_Response(); $response->set_matched_route( $match[0] ); $response->set_matched_handler( $match[1] ); $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); foreach ( $headers as $name => $value ) { $name = WP_REST_Request::canonicalize_header_name( $name ); $target_hints[ $name ] = array_map( 'trim', explode( ',', $value ) ); } return $target_hints; } /** * Retrieves the CURIEs (compact URIs) used for relations. * * Extracts the links from a response into a structured hash, suitable for * direct output. * * @since 4.5.0 * * @param WP_REST_Response $response Response to extract links from. * @return array Map of link relation to list of link hashes. */ public static function get_compact_response_links( $response ) { $links = self::get_response_links( $response ); if ( empty( $links ) ) { return array(); } $curies = $response->get_curies(); $used_curies = array(); foreach ( $links as $rel => $items ) { // Convert $rel URIs to their compact versions if they exist. foreach ( $curies as $curie ) { $href_prefix = substr( $curie['href'], 0, strpos( $curie['href'], '{rel}' ) ); if ( ! str_starts_with( $rel, $href_prefix ) ) { continue; } // Relation now changes from '$uri' to '$curie:$relation'. $rel_regex = str_replace( '\{rel\}', '(.+)', preg_quote( $curie['href'], '!' ) ); preg_match( '!' . $rel_regex . '!', $rel, $matches ); if ( $matches ) { $new_rel = $curie['name'] . ':' . $matches[1]; $used_curies[ $curie['name'] ] = $curie; $links[ $new_rel ] = $items; unset( $links[ $rel ] ); break; } } } // Push the curies onto the start of the links array. if ( $used_curies ) { $links['curies'] = array_values( $used_curies ); } return $links; } /** * Embeds the links from the data into the request. * * @since 4.4.0 * @since 5.4.0 The `$embed` parameter can now contain a list of link relations to include. * * @param array $data Data from the request. * @param bool|string[] $embed Whether to embed all links or a filtered list of link relations. * Default true. * @return array { * Data with sub-requests embedded. * * @type array $_links Links. * @type array $_embedded Embedded objects. * } */ protected function embed_links( $data, $embed = true ) { if ( empty( $data['_links'] ) ) { return $data; } $embedded = array(); foreach ( $data['_links'] as $rel => $links ) { /* * If a list of relations was specified, and the link relation * is not in the list of allowed relations, don't process the link. */ if ( is_array( $embed ) && ! in_array( $rel, $embed, true ) ) { continue; } $embeds = array(); foreach ( $links as $item ) { // Determine if the link is embeddable. if ( empty( $item['embeddable'] ) ) { // Ensure we keep the same order. $embeds[] = array(); continue; } if ( ! array_key_exists( $item['href'], $this->embed_cache ) ) { // Run through our internal routing and serve. $request = WP_REST_Request::from_url( $item['href'] ); if ( ! $request ) { $embeds[] = array(); continue; } // Embedded resources get passed context=embed. if ( empty( $request['context'] ) ) { $request['context'] = 'embed'; } if ( empty( $request['per_page'] ) ) { $matched = $this->match_request_to_handler( $request ); if ( ! is_wp_error( $matched ) && isset( $matched[1]['args']['per_page']['maximum'] ) ) { $request['per_page'] = (int) $matched[1]['args']['per_page']['maximum']; } } $response = $this->dispatch( $request ); /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $this, $request ); $this->embed_cache[ $item['href'] ] = $this->response_to_data( $response, false ); } $embeds[] = $this->embed_cache[ $item['href'] ]; } // Determine if any real links were found. $has_links = count( array_filter( $embeds ) ); if ( $has_links ) { $embedded[ $rel ] = $embeds; } } if ( ! empty( $embedded ) ) { $data['_embedded'] = $embedded; } return $data; } /** * Wraps the response in an envelope. * * The enveloping technique is used to work around browser/client * compatibility issues. Essentially, it converts the full HTTP response to * data instead. * * @since 4.4.0 * @since 6.0.0 The `$embed` parameter can now contain a list of link relations to include. * * @param WP_REST_Response $response Response object. * @param bool|string[] $embed Whether to embed all links, a filtered list of link relations, or no links. * @return WP_REST_Response New response with wrapped data */ public function envelope_response( $response, $embed ) { $envelope = array( 'body' => $this->response_to_data( $response, $embed ), 'status' => $response->get_status(), 'headers' => $response->get_headers(), ); /** * Filters the enveloped form of a REST API response. * * @since 4.4.0 * * @param array $envelope { * Envelope data. * * @type array $body Response data. * @type int $status The 3-digit HTTP status code. * @type array $headers Map of header name to header value. * } * @param WP_REST_Response $response Original response data. */ $envelope = apply_filters( 'rest_envelope_response', $envelope, $response ); // Ensure it's still a response and return. return rest_ensure_response( $envelope ); } /** * Registers a route to the server. * * @since 4.4.0 * * @param string $route_namespace Namespace. * @param string $route The REST route. * @param array $route_args Route arguments. * @param bool $override Optional. Whether the route should be overridden if it already exists. * Default false. */ public function register_route( $route_namespace, $route, $route_args, $override = false ) { if ( ! isset( $this->namespaces[ $route_namespace ] ) ) { $this->namespaces[ $route_namespace ] = array(); $this->register_route( $route_namespace, '/' . $route_namespace, array( array( 'methods' => self::READABLE, 'callback' => array( $this, 'get_namespace_index' ), 'args' => array( 'namespace' => array( 'default' => $route_namespace, ), 'context' => array( 'default' => 'view', ), ), ), ) ); } // Associative to avoid double-registration. $this->namespaces[ $route_namespace ][ $route ] = true; $route_args['namespace'] = $route_namespace; if ( $override || empty( $this->endpoints[ $route ] ) ) { $this->endpoints[ $route ] = $route_args; } else { $this->endpoints[ $route ] = array_merge( $this->endpoints[ $route ], $route_args ); } } /** * Retrieves the route map. * * The route map is an associative array with path regexes as the keys. The * value is an indexed array with the callback function/method as the first * item, and a bitmask of HTTP methods as the second item (see the class * constants). * * Each route can be mapped to more than one callback by using an array of * the indexed arrays. This allows mapping e.g. GET requests to one callback * and POST requests to another. * * Note that the path regexes (array keys) must have @ escaped, as this is * used as the delimiter with preg_match() * * @since 4.4.0 * @since 5.4.0 Added `$route_namespace` parameter. * * @param string $route_namespace Optionally, only return routes in the given namespace. * @return array `'/path/regex' => array( $callback, $bitmask )` or * `'/path/regex' => array( array( $callback, $bitmask ), ...)`. */ public function get_routes( $route_namespace = '' ) { $endpoints = $this->endpoints; if ( $route_namespace ) { $endpoints = wp_list_filter( $endpoints, array( 'namespace' => $route_namespace ) ); } /** * Filters the array of available REST API endpoints. * * @since 4.4.0 * * @param array $endpoints The available endpoints. An array of matching regex patterns, each mapped * to an array of callbacks for the endpoint. These take the format * `'/path/regex' => array( $callback, $bitmask )` or * `'/path/regex' => array( array( $callback, $bitmask ). */ $endpoints = apply_filters( 'rest_endpoints', $endpoints ); // Normalize the endpoints. $defaults = array( 'methods' => '', 'accept_json' => false, 'accept_raw' => false, 'show_in_index' => true, 'args' => array(), ); foreach ( $endpoints as $route => &$handlers ) { if ( isset( $handlers['callback'] ) ) { // Single endpoint, add one deeper. $handlers = array( $handlers ); } if ( ! isset( $this->route_options[ $route ] ) ) { $this->route_options[ $route ] = array(); } foreach ( $handlers as $key => &$handler ) { if ( ! is_numeric( $key ) ) { // Route option, move it to the options. $this->route_options[ $route ][ $key ] = $handler; unset( $handlers[ $key ] ); continue; } $handler = wp_parse_args( $handler, $defaults ); // Allow comma-separated HTTP methods. if ( is_string( $handler['methods'] ) ) { $methods = explode( ',', $handler['methods'] ); } elseif ( is_array( $handler['methods'] ) ) { $methods = $handler['methods']; } else { $methods = array(); } $handler['methods'] = array(); foreach ( $methods as $method ) { $method = strtoupper( trim( $method ) ); $handler['methods'][ $method ] = true; } } } return $endpoints; } /** * Retrieves namespaces registered on the server. * * @since 4.4.0 * * @return string[] List of registered namespaces. */ public function get_namespaces() { return array_keys( $this->namespaces ); } /** * Retrieves specified options for a route. * * @since 4.4.0 * * @param string $route Route pattern to fetch options for. * @return array|null Data as an associative array if found, or null if not found. */ public function get_route_options( $route ) { if ( ! isset( $this->route_options[ $route ] ) ) { return null; } return $this->route_options[ $route ]; } /** * Matches the request to a callback and call it. * * @since 4.4.0 * * @param WP_REST_Request $request Request to attempt dispatching. * @return WP_REST_Response Response returned by the callback. */ public function dispatch( $request ) { $this->dispatching_requests[] = $request; /** * Filters the pre-calculated result of a REST API dispatch request. * * Allow hijacking the request before dispatching by returning a non-empty. The returned value * will be used to serve the request instead. * * @since 4.4.0 * * @param mixed $result Response to replace the requested version with. Can be anything * a normal endpoint can return, or null to not hijack the request. * @param WP_REST_Server $server Server instance. * @param WP_REST_Request $request Request used to generate the response. */ $result = apply_filters( 'rest_pre_dispatch', null, $this, $request ); if ( ! empty( $result ) ) { // Normalize to either WP_Error or WP_REST_Response... $result = rest_ensure_response( $result ); // ...then convert WP_Error across. if ( is_wp_error( $result ) ) { $result = $this->error_to_response( $result ); } array_pop( $this->dispatching_requests ); return $result; } $error = null; $matched = $this->match_request_to_handler( $request ); if ( is_wp_error( $matched ) ) { $response = $this->error_to_response( $matched ); array_pop( $this->dispatching_requests ); return $response; } list( $route, $handler ) = $matched; if ( ! is_callable( $handler['callback'] ) ) { $error = new WP_Error( 'rest_invalid_handler', __( 'The handler for the route is invalid.' ), array( 'status' => 500 ) ); } if ( ! is_wp_error( $error ) ) { $check_required = $request->has_valid_params(); if ( is_wp_error( $check_required ) ) { $error = $check_required; } else { $check_sanitized = $request->sanitize_params(); if ( is_wp_error( $check_sanitized ) ) { $error = $check_sanitized; } } } $response = $this->respond_to_request( $request, $route, $handler, $error ); array_pop( $this->dispatching_requests ); return $response; } /** * Returns whether the REST server is currently dispatching / responding to a request. * * This may be a standalone REST API request, or an internal request dispatched from within a regular page load. * * @since 6.5.0 * * @return bool Whether the REST server is currently handling a request. */ public function is_dispatching() { return (bool) $this->dispatching_requests; } /** * Matches a request object to its handler. * * @access private * @since 5.6.0 * * @param WP_REST_Request $request The request object. * @return array|WP_Error The route and request handler on success or a WP_Error instance if no handler was found. */ protected function match_request_to_handler( $request ) { $method = $request->get_method(); $path = $request->get_route(); $with_namespace = array(); foreach ( $this->get_namespaces() as $namespace ) { if ( str_starts_with( trailingslashit( ltrim( $path, '/' ) ), $namespace ) ) { $with_namespace[] = $this->get_routes( $namespace ); } } if ( $with_namespace ) { $routes = array_merge( ...$with_namespace ); } else { $routes = $this->get_routes(); } foreach ( $routes as $route => $handlers ) { $match = preg_match( '@^' . $route . '$@i', $path, $matches ); if ( ! $match ) { continue; } $args = array(); foreach ( $matches as $param => $value ) { if ( ! is_int( $param ) ) { $args[ $param ] = $value; } } foreach ( $handlers as $handler ) { $callback = $handler['callback']; // Fallback to GET method if no HEAD method is registered. $checked_method = $method; if ( 'HEAD' === $method && empty( $handler['methods']['HEAD'] ) ) { $checked_method = 'GET'; } if ( empty( $handler['methods'][ $checked_method ] ) ) { continue; } if ( ! is_callable( $callback ) ) { return array( $route, $handler ); } $request->set_url_params( $args ); $request->set_attributes( $handler ); $defaults = array(); foreach ( $handler['args'] as $arg => $options ) { if ( isset( $options['default'] ) ) { $defaults[ $arg ] = $options['default']; } } $request->set_default_params( $defaults ); return array( $route, $handler ); } } return new WP_Error( 'rest_no_route', __( 'No route was found matching the URL and request method.' ), array( 'status' => 404 ) ); } /** * Dispatches the request to the callback handler. * * @access private * @since 5.6.0 * * @param WP_REST_Request $request The request object. * @param string $route The matched route regex. * @param array $handler The matched route handler. * @param WP_Error|null $response The current error object if any. * @return WP_REST_Response */ protected function respond_to_request( $request, $route, $handler, $response ) { /** * Filters the response before executing any REST API callbacks. * * Allows plugins to perform additional validation after a * request is initialized and matched to a registered route, * but before it is executed. * * Note that this filter will not be called for requests that * fail to authenticate or match to a registered route. * * @since 4.7.0 * * @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. * @param array $handler Route handler used for the request. * @param WP_REST_Request $request Request used to generate the response. */ $response = apply_filters( 'rest_request_before_callbacks', $response, $handler, $request ); // Check permission specified on the route. if ( ! is_wp_error( $response ) && ! empty( $handler['permission_callback'] ) ) { $permission = call_user_func( $handler['permission_callback'], $request ); if ( is_wp_error( $permission ) ) { $response = $permission; } elseif ( false === $permission || null === $permission ) { $response = new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to do that.' ), array( 'status' => rest_authorization_required_code() ) ); } } if ( ! is_wp_error( $response ) ) { /** * Filters the REST API dispatch request result. * * Allow plugins to override dispatching the request. * * @since 4.4.0 * @since 4.5.0 Added `$route` and `$handler` parameters. * * @param mixed $dispatch_result Dispatch result, will be used if not empty. * @param WP_REST_Request $request Request used to generate the response. * @param string $route Route matched for the request. * @param array $handler Route handler used for the request. */ $dispatch_result = apply_filters( 'rest_dispatch_request', null, $request, $route, $handler ); // Allow plugins to halt the request via this filter. if ( null !== $dispatch_result ) { $response = $dispatch_result; } else { $response = call_user_func( $handler['callback'], $request ); } } /** * Filters the response immediately after executing any REST API * callbacks. * * Allows plugins to perform any needed cleanup, for example, * to undo changes made during the {@see 'rest_request_before_callbacks'} * filter. * * Note that this filter will not be called for requests that * fail to authenticate or match to a registered route. * * Note that an endpoint's `permission_callback` can still be * called after this filter - see `rest_send_allow_header()`. * * @since 4.7.0 * * @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. * @param array $handler Route handler used for the request. * @param WP_REST_Request $request Request used to generate the response. */ $response = apply_filters( 'rest_request_after_callbacks', $response, $handler, $request ); if ( is_wp_error( $response ) ) { $response = $this->error_to_response( $response ); } else { $response = rest_ensure_response( $response ); } $response->set_matched_route( $route ); $response->set_matched_handler( $handler ); return $response; } /** * Returns if an error occurred during most recent JSON encode/decode. * * Strings to be translated will be in format like * "Encoding error: Maximum stack depth exceeded". * * @since 4.4.0 * * @return false|string Boolean false or string error message. */ protected function get_json_last_error() { if ( JSON_ERROR_NONE === json_last_error() ) { return false; } return json_last_error_msg(); } /** * Retrieves the site index. * * This endpoint describes the capabilities of the site. * * @since 4.4.0 * * @param WP_REST_Request $request Request data. * @return WP_REST_Response The API root index data. */ public function get_index( $request ) { // General site data. $available = array( 'name' => get_option( 'blogname' ), 'description' => get_option( 'blogdescription' ), 'url' => get_option( 'siteurl' ), 'home' => home_url(), 'gmt_offset' => get_option( 'gmt_offset' ), 'timezone_string' => get_option( 'timezone_string' ), 'page_for_posts' => (int) get_option( 'page_for_posts' ), 'page_on_front' => (int) get_option( 'page_on_front' ), 'show_on_front' => get_option( 'show_on_front' ), 'namespaces' => array_keys( $this->namespaces ), 'authentication' => array(), 'routes' => $this->get_data_for_routes( $this->get_routes(), $request['context'] ), ); // Add media processing settings for users who can upload files. if ( wp_is_client_side_media_processing_enabled() && current_user_can( 'upload_files' ) ) { // Image sizes keyed by name for client-side media processing. $available['image_sizes'] = array(); foreach ( wp_get_registered_image_subsizes() as $name => $size ) { $available['image_sizes'][ $name ] = $size; } /** This filter is documented in wp-admin/includes/image.php */ $available['image_size_threshold'] = (int) apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 ); /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ $available['image_strip_meta'] = (bool) apply_filters( 'image_strip_meta', true ); /* * On the server, this filter receives the decoded image's actual bit depth. * The client path never decodes the image on the server, so the filter is * applied with 16 (the maximum depth the client encoder can produce) as * both the value and the current depth. The client caps its output bit * depth at the filtered value, so a plugin lowering it (e.g. to 8) takes * effect on client-generated images too. */ /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ $available['image_max_bit_depth'] = (int) apply_filters( 'image_max_bit_depth', 16, 16 ); } $response = new WP_REST_Response( $available ); $fields = $request['_fields'] ?? ''; $fields = wp_parse_list( $fields ); if ( empty( $fields ) ) { $fields[] = '_links'; } if ( $request->has_param( '_embed' ) ) { $fields[] = '_embedded'; } if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { $response->add_link( 'help', 'https://developer.wordpress.org/rest-api/' ); $this->add_active_theme_link_to_index( $response ); $this->add_site_logo_to_index( $response ); $this->add_site_icon_to_index( $response ); } else { if ( rest_is_field_included( 'site_logo', $fields ) ) { $this->add_site_logo_to_index( $response ); } if ( rest_is_field_included( 'site_icon', $fields ) || rest_is_field_included( 'site_icon_url', $fields ) ) { $this->add_site_icon_to_index( $response ); } } /** * Filters the REST API root index data. * * This contains the data describing the API. This includes information * about supported authentication schemes, supported namespaces, routes * available on the API, and a small amount of data about the site. * * @since 4.4.0 * @since 6.0.0 Added `$request` parameter. * * @param WP_REST_Response $response Response data. * @param WP_REST_Request $request Request data. */ return apply_filters( 'rest_index', $response, $request ); } /** * Adds a link to the active theme for users who have proper permissions. * * @since 5.7.0 * * @param WP_REST_Response $response REST API response. */ protected function add_active_theme_link_to_index( WP_REST_Response $response ) { $should_add = current_user_can( 'switch_themes' ) || current_user_can( 'manage_network_themes' ); if ( ! $should_add && current_user_can( 'edit_posts' ) ) { $should_add = true; } if ( ! $should_add ) { foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { if ( current_user_can( $post_type->cap->edit_posts ) ) { $should_add = true; break; } } } if ( $should_add ) { $theme = wp_get_theme(); $response->add_link( 'https://api.w.org/active-theme', rest_url( 'wp/v2/themes/' . $theme->get_stylesheet() ) ); } } /** * Exposes the site logo through the WordPress REST API. * * This is used for fetching this information when user has no rights * to update settings. * * @since 5.8.0 * * @param WP_REST_Response $response REST API response. */ protected function add_site_logo_to_index( WP_REST_Response $response ) { $site_logo_id = get_theme_mod( 'custom_logo', 0 ); $this->add_image_to_index( $response, $site_logo_id, 'site_logo' ); } /** * Exposes the site icon through the WordPress REST API. * * This is used for fetching this information when user has no rights * to update settings. * * @since 5.9.0 * * @param WP_REST_Response $response REST API response. */ protected function add_site_icon_to_index( WP_REST_Response $response ) { $site_icon_id = get_option( 'site_icon', 0 ); $this->add_image_to_index( $response, $site_icon_id, 'site_icon' ); $response->data['site_icon_url'] = get_site_icon_url(); } /** * Exposes an image through the WordPress REST API. * This is used for fetching this information when user has no rights * to update settings. * * @since 5.9.0 * * @param WP_REST_Response $response REST API response. * @param int $image_id Image attachment ID. * @param string $type Type of Image. */ protected function add_image_to_index( WP_REST_Response $response, $image_id, $type ) { $response->data[ $type ] = (int) $image_id; if ( $image_id ) { $response->add_link( 'https://api.w.org/featuredmedia', rest_url( rest_get_route_for_post( $image_id ) ), array( 'embeddable' => true, 'type' => $type, ) ); } } /** * Retrieves the index for a namespace. * * @since 4.4.0 * * @param WP_REST_Request $request REST request instance. * @return WP_REST_Response|WP_Error WP_REST_Response instance if the index was found, * WP_Error if the namespace isn't set. */ public function get_namespace_index( $request ) { $namespace = $request['namespace']; if ( ! isset( $this->namespaces[ $namespace ] ) ) { return new WP_Error( 'rest_invalid_namespace', __( 'The specified namespace could not be found.' ), array( 'status' => 404 ) ); } $routes = $this->namespaces[ $namespace ]; $endpoints = array_intersect_key( $this->get_routes(), $routes ); $data = array( 'namespace' => $namespace, 'routes' => $this->get_data_for_routes( $endpoints, $request['context'] ), ); $response = rest_ensure_response( $data ); // Link to the root index. $response->add_link( 'up', rest_url( '/' ) ); /** * Filters the REST API namespace index data. * * This typically is just the route data for the namespace, but you can * add any data you'd like here. * * @since 4.4.0 * * @param WP_REST_Response $response Response data. * @param WP_REST_Request $request Request data. The namespace is passed as the 'namespace' parameter. */ return apply_filters( 'rest_namespace_index', $response, $request ); } /** * Retrieves the publicly-visible data for routes. * * @since 4.4.0 * * @param array $routes Routes to get data for. * @param string $context Optional. Context for data. Accepts 'view' or 'help'. Default 'view'. * @return array[] Route data to expose in indexes, keyed by route. */ public function get_data_for_routes( $routes, $context = 'view' ) { $available = array(); // Find the available routes. foreach ( $routes as $route => $callbacks ) { $data = $this->get_data_for_route( $route, $callbacks, $context ); if ( empty( $data ) ) { continue; } /** * Filters the publicly-visible data for a single REST API route. * * @since 4.4.0 * * @param array $data Publicly-visible data for the route. */ $available[ $route ] = apply_filters( 'rest_endpoints_description', $data ); } /** * Filters the publicly-visible data for REST API routes. * * This data is exposed on indexes and can be used by clients or * developers to investigate the site and find out how to use it. It * acts as a form of self-documentation. * * @since 4.4.0 * * @param array[] $available Route data to expose in indexes, keyed by route. * @param array $routes Internal route data as an associative array. */ return apply_filters( 'rest_route_data', $available, $routes ); } /** * Retrieves publicly-visible data for the route. * * @since 4.4.0 * * @param string $route Route to get data for. * @param array $callbacks Callbacks to convert to data. * @param string $context Optional. Context for the data. Accepts 'view' or 'help'. Default 'view'. * @return array|null Data for the route, or null if no publicly-visible data. */ public function get_data_for_route( $route, $callbacks, $context = 'view' ) { $data = array( 'namespace' => '', 'methods' => array(), 'endpoints' => array(), ); $allow_batch = false; if ( isset( $this->route_options[ $route ] ) ) { $options = $this->route_options[ $route ]; if ( isset( $options['namespace'] ) ) { $data['namespace'] = $options['namespace']; } $allow_batch = $options['allow_batch'] ?? false; if ( isset( $options['schema'] ) && 'help' === $context ) { $data['schema'] = call_user_func( $options['schema'] ); } } $allowed_schema_keywords = array_flip( wp_get_json_schema_allowed_keywords( 'rest-api' ) ); $route = preg_replace( '#\(\?P<(\w+?)>.*?\)#', '{$1}', $route ); foreach ( $callbacks as $callback ) { // Skip to the next route if any callback is hidden. if ( empty( $callback['show_in_index'] ) ) { continue; } $data['methods'] = array_merge( $data['methods'], array_keys( $callback['methods'] ) ); $endpoint_data = array( 'methods' => array_keys( $callback['methods'] ), ); $callback_batch = $callback['allow_batch'] ?? $allow_batch; if ( $callback_batch ) { $endpoint_data['allow_batch'] = $callback_batch; } if ( isset( $callback['args'] ) ) { $endpoint_data['args'] = array(); foreach ( $callback['args'] as $key => $opts ) { if ( is_string( $opts ) ) { $opts = array( $opts => 0 ); } elseif ( ! is_array( $opts ) ) { $opts = array(); } $arg_data = array_intersect_key( $opts, $allowed_schema_keywords ); $arg_data['required'] = ! empty( $opts['required'] ); $endpoint_data['args'][ $key ] = $arg_data; } } $data['endpoints'][] = $endpoint_data; // For non-variable routes, generate links. if ( ! str_contains( $route, '{' ) ) { $data['_links'] = array( 'self' => array( array( 'href' => rest_url( $route ), ), ), ); } } if ( empty( $data['methods'] ) ) { // No methods supported, hide the route. return null; } return $data; } /** * Gets the maximum number of requests that can be included in a batch. * * @since 5.6.0 * * @return int The maximum requests. */ protected function get_max_batch_size() { /** * Filters the maximum number of REST API requests that can be included in a batch. * * @since 5.6.0 * * @param int $max_size The maximum size. */ return apply_filters( 'rest_get_max_batch_size', 25 ); } /** * Serves the batch/v1 request. * * @since 5.6.0 * * @param WP_REST_Request $batch_request The batch request object. * @return WP_REST_Response The generated response object. */ public function serve_batch_request_v1( WP_REST_Request $batch_request ) { $requests = array(); foreach ( $batch_request['requests'] as $args ) { $parsed_url = wp_parse_url( $args['path'] ); if ( false === $parsed_url ) { $requests[] = new WP_Error( 'parse_path_failed', __( 'Could not parse the path.' ), array( 'status' => 400 ) ); continue; } $single_request = new WP_REST_Request( $args['method'] ?? 'POST', $parsed_url['path'] ); if ( ! empty( $parsed_url['query'] ) ) { $query_args = array(); wp_parse_str( $parsed_url['query'], $query_args ); $single_request->set_query_params( $query_args ); } if ( ! empty( $args['body'] ) ) { $single_request->set_body_params( $args['body'] ); } if ( ! empty( $args['headers'] ) ) { $single_request->set_headers( $args['headers'] ); } $requests[] = $single_request; } $matches = array(); $validation = array(); $has_error = false; foreach ( $requests as $single_request ) { if ( is_wp_error( $single_request ) ) { $has_error = true; $matches[] = $single_request; $validation[] = $single_request; continue; } $match = $this->match_request_to_handler( $single_request ); $matches[] = $match; $error = null; if ( is_wp_error( $match ) ) { $error = $match; } if ( ! $error ) { list( $route, $handler ) = $match; if ( isset( $handler['allow_batch'] ) ) { $allow_batch = $handler['allow_batch']; } else { $route_options = $this->get_route_options( $route ); $allow_batch = $route_options['allow_batch'] ?? false; } if ( ! is_array( $allow_batch ) || empty( $allow_batch['v1'] ) ) { $error = new WP_Error( 'rest_batch_not_allowed', __( 'The requested route does not support batch requests.' ), array( 'status' => 400 ) ); } } if ( ! $error ) { $check_required = $single_request->has_valid_params(); if ( is_wp_error( $check_required ) ) { $error = $check_required; } } if ( ! $error ) { $check_sanitized = $single_request->sanitize_params(); if ( is_wp_error( $check_sanitized ) ) { $error = $check_sanitized; } } if ( $error ) { $has_error = true; $validation[] = $error; } else { $validation[] = true; } } $responses = array(); if ( $has_error && 'require-all-validate' === $batch_request['validation'] ) { foreach ( $validation as $valid ) { if ( is_wp_error( $valid ) ) { $responses[] = $this->envelope_response( $this->error_to_response( $valid ), false )->get_data(); } else { $responses[] = null; } } return new WP_REST_Response( array( 'failed' => 'validation', 'responses' => $responses, ), WP_Http::MULTI_STATUS ); } foreach ( $requests as $i => $single_request ) { if ( is_wp_error( $single_request ) ) { $result = $this->error_to_response( $single_request ); $responses[] = $this->envelope_response( $result, false )->get_data(); continue; } $clean_request = clone $single_request; $clean_request->set_url_params( array() ); $clean_request->set_attributes( array() ); $clean_request->set_default_params( array() ); /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ $result = apply_filters( 'rest_pre_dispatch', null, $this, $clean_request ); if ( empty( $result ) ) { $match = $matches[ $i ]; $error = null; if ( is_wp_error( $validation[ $i ] ) ) { $error = $validation[ $i ]; } if ( is_wp_error( $match ) ) { $result = $this->error_to_response( $match ); } else { list( $route, $handler ) = $match; if ( ! $error && ! is_callable( $handler['callback'] ) ) { $error = new WP_Error( 'rest_invalid_handler', __( 'The handler for the route is invalid' ), array( 'status' => 500 ) ); } $result = $this->respond_to_request( $single_request, $route, $handler, $error ); } } /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ $result = apply_filters( 'rest_post_dispatch', rest_ensure_response( $result ), $this, $single_request ); $responses[] = $this->envelope_response( $result, false )->get_data(); } return new WP_REST_Response( array( 'responses' => $responses ), WP_Http::MULTI_STATUS ); } /** * Sends an HTTP status code. * * @since 4.4.0 * * @param int $code HTTP status. */ protected function set_status( $code ) { status_header( $code ); } /** * Sends an HTTP header. * * @since 4.4.0 * * @param string $key Header key. * @param string $value Header value. */ public function send_header( $key, $value ) { /* * Sanitize as per RFC2616 (Section 4.2): * * Any LWS that occurs between field-content MAY be replaced with a * single SP before interpreting the field value or forwarding the * message downstream. */ $value = preg_replace( '/\s+/', ' ', $value ); header( sprintf( '%s: %s', $key, $value ) ); } /** * Sends multiple HTTP headers. * * @since 4.4.0 * * @param array $headers Map of header name to header value. */ public function send_headers( $headers ) { foreach ( $headers as $key => $value ) { $this->send_header( $key, $value ); } } /** * Removes an HTTP header from the current response. * * @since 4.8.0 * * @param string $key Header key. */ public function remove_header( $key ) { header_remove( $key ); } /** * Retrieves the raw request entity (body). * * @since 4.4.0 * * @global string $HTTP_RAW_POST_DATA Raw post data. * * @return string Raw request data. */ public static function get_raw_data() { // phpcs:disable PHPCompatibility.Variables.RemovedPredefinedGlobalVariables.http_raw_post_dataDeprecatedRemoved global $HTTP_RAW_POST_DATA; // $HTTP_RAW_POST_DATA was deprecated in PHP 5.6 and removed in PHP 7.0. if ( ! isset( $HTTP_RAW_POST_DATA ) ) { $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); } return $HTTP_RAW_POST_DATA; // phpcs:enable } /** * Extracts headers from a PHP-style $_SERVER array. * * @since 4.4.0 * * @param array $server Associative array similar to `$_SERVER`. * @return array Headers extracted from the input. */ public function get_headers( $server ) { $headers = array(); // CONTENT_* headers are not prefixed with HTTP_. $additional = array( 'CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true, ); foreach ( $server as $key => $value ) { if ( str_starts_with( $key, 'HTTP_' ) ) { $headers[ substr( $key, 5 ) ] = $value; } elseif ( 'REDIRECT_HTTP_AUTHORIZATION' === $key && empty( $server['HTTP_AUTHORIZATION'] ) ) { /* * In some server configurations, the authorization header is passed in this alternate location. * Since it would not be passed in both places we do not check for both headers and resolve. */ $headers['AUTHORIZATION'] = $value; } elseif ( isset( $additional[ $key ] ) ) { $headers[ $key ] = $value; } } return $headers; } } NVIDIA | ZIRAN Comunicación https://www.ziran.es Comunicación Estratégica Thu, 20 Aug 2026 15:37:18 +0000 es hourly 1 https://wordpress.org/?v=7.1 https://www.ziran.es/wp-content/uploads/2020/07/favicon.svg NVIDIA | ZIRAN Comunicación https://www.ziran.es 32 32 GeForce NOW llega a Firefox añadiendo 12 juegos a su biblioteca https://www.ziran.es/nota_prensa/geforce-now-llega-a-firefox-anadiendo-12-juegos-a-su-biblioteca/ Thu, 20 Aug 2026 15:37:18 +0000 https://www.ziran.es/?post_type=nota_prensa&p=68646 NVIDIA ha anunciado las novedades de esta semana para GeForce NOW. La plataforma de videojugos en la nube se estrena en el navegador Firefox para Windows, proporcionando a los usuarios una nueva vía para acceder a sus videojuegos favoritos con toda la potencia de los mejores PC gaming. Además, durante estos días, la biblioteca del […]

La entrada GeForce NOW llega a Firefox añadiendo 12 juegos a su biblioteca apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha anunciado las novedades de esta semana para GeForce NOW. La plataforma de videojugos en la nube se estrena en el navegador Firefox para Windows, proporcionando a los usuarios una nueva vía para acceder a sus videojuegos favoritos con toda la potencia de los mejores PC gaming. Además, durante estos días, la biblioteca del servicio recibirá 12 nuevos títulos, con lanzamientos como The Sinking City 2Gallipoli y Stars Reach.

A partir de ahora, los usuarios de Firefox en Windows podrán disfrutar de la mejor versión de sus títulos preferidos sin necesidad de descargar nada, directamente desde la nube. Sin aplicación dedicada, sin descargas ni espacio dedicado a las instalaciones. Aquellos que dispongan de una suscripción Ultimate, podrán jugar a los títulos compatibles con toda la potencia de GeForce RTX, en partidas hasta a 1440p y 120 frames por segundo.

NVIDIA también ha destacado los juegos que se sumarán a la biblioteca de GeForce NOW a partir de esta semana, con novedades como Gallipoli, la última entrega de la saga WW1 Game Series. Los miembros del servicio podrán enfrentarse en batallas por objetivos de 25 contra 25 a lo largo de los frentes otomanos y continuar con la acción en cualquier lugar gracias a las partidas guardadas en la nube en cualquiera de sus dispositivos. A continuación, se detalla la lista completa:

  • Stars Reach (Nuevo en Steam)
  • The Sinking City 2 (Nuevo en Steam)
  • Gallipoli (Nuevo en Steam)
  • DIVE or DIE – Children of Rain (Steam)
  • Escape the Backroom (Xbox, Game Pass)
  • Hell Is Us (Xbox, Game Pass)
  • High on Life (Steam)
  • High on Life 2 (Steam y Xbox, Game Pass)
  • Parcel Simulator (Steam)
  • Starvester (Steam)
  • The Thaumaturge (Xbox, available on Game Pass)
  • Tomb Raider IV-VI Remastered (Epic Games Store)

GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.

Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

La entrada GeForce NOW llega a Firefox añadiendo 12 juegos a su biblioteca apareció primero en ZIRAN Comunicación.]]>
GeForce NOW llega a Firefox https://www.ziran.es/nota_prensa/geforce-now-llega-a-firefox/ Wed, 19 Aug 2026 14:53:07 +0000 https://www.ziran.es/?post_type=nota_prensa&p=68493 NVIDIA ha anunciado que, a partir de ahora, los usuarios de Firefox podrán disfrutar a través de GeForce NOW de más de 5000 juegos de PC, de plataformas  como Steam, Epic Games, Xbox / PC Game Pass y Ubisoft Connect, desde la nube y sin perder el tiempo con descargas ni ocupar espacio con instalaciones en el equipo. Los […]

La entrada GeForce NOW llega a Firefox apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha anunciado que, a partir de ahora, los usuarios de Firefox podrán disfrutar a través de GeForce NOW de más de 5000 juegos de PC, de plataformas  como Steam, Epic Games, Xbox / PC Game Pass y Ubisoft Connect, desde la nube y sin perder el tiempo con descargas ni ocupar espacio con instalaciones en el equipo.

Los miembros de GeForce NOW Ultimate podrán disfrutar del cloud gaming más avanzado, con partidas a 1440p y 120 cuadros por segundo, directamente desde el navegador Firefox.

Este lanzamiento llega tras meses de colaboración entre Mozilla y NVIDIA GeForce NOW para acercar la experiencia del juego en la nube a los usuarios de Firefox, facilitando a los jugadores una nueva manera de disfrutar de sus colecciones en cualquier parte. Para probarlo, los usuarios deberán descargar la versión más reciente de Firefox y visitar play.geforcenow.com para empezar a jugar.

GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.

Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

 

 

La entrada GeForce NOW llega a Firefox apareció primero en ZIRAN Comunicación.]]>
NVIDIA anuncia la llegada de nuevos juegos con tecnologías RTX https://www.ziran.es/nota_prensa/nvidia-anuncia-la-llegada-de-nuevos-juegos-con-tecnologias-rtx-2/ Tue, 18 Aug 2026 13:24:45 +0000 https://www.ziran.es/?post_type=nota_prensa&p=68389 NVIDIA ha destacado los títulos que llegarán esta semana con tecnologías RTX. Destacan videojuegos como Mortal Shell II, The Sinking City 2 y en Acceso Anticipado de Luminary, que estarán disponibles con DLSS. Mortal Shell II, el nuevo juego de Cold Symmetry y Playstack, amplía significativamente la fórmula del souls-like original con un combate libre y cargado de adrenalina, […]

La entrada NVIDIA anuncia la llegada de nuevos juegos con tecnologías RTX apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha destacado los títulos que llegarán esta semana con tecnologías RTX. Destacan videojuegos como Mortal Shell IIThe Sinking City 2 y en Acceso Anticipado de Luminary, que estarán disponibles con DLSS.

  • Mortal Shell II, el nuevo juego de Cold Symmetry y Playstack, amplía significativamente la fórmula del souls-like original con un combate libre y cargado de adrenalina, un diseño de armas más profundo (con amplias opciones de mejora) y una gran libertad a la hora de explorar. Mortal Shell II ya está disponible en acceso anticipado (Advance Access) para quienes hayan adquirido la Devout Edition, mientras que el lanzamiento oficial tendrá lugar el 20 de agosto. Los jugadores podrán vitaminar su experiencia con DLSS 4.5 Super Resolution y Multi Frame Generation, mejorar la calidad de la imagen activando los reflejos y la iluminación global con trazado de rayos, y potenciar el rendimiento en las GPU GeForce RTX Serie 50 activando Dynamic Multi Frame Generation desde la app de NVIDIA.
  • The Sinking City 2, del reconocido estudio Frogwares, nos traslada a una visión lovecraftiana de los Estados Unidos de la década de 1920, en la infame ciudad de Arkham. Una inundación sobrenatural ha ahuyentado a todos los habitantes excepto a los más trastornados, dejando a su paso decadencia y horrores cósmicos que deambulan por las calles. Los jugadores se pondrán en la piel de Calvin Rafferty, un investigador de lo oculto cuyas temerarias acciones han tenido consecuencias devastadoras. Calvin deberá recorrer las calles anegadas de una ciudad en ruinas en un intento desesperado por traerla de vuelta a la normalidad. The Sinking City 2 se ha lanzado hoy mismo, y todos los jugadores con una GPU GeForce RTX podrán acelerar y mejorar su experiencia utilizando DLSS 4.5 Super Resolution y Multi Frame Generation, tecnología que se puede actualizar a Dynamic Multi Frame Generation a través de NVIDIA app.
  • Refractive Entertainment, un equipo formado por tan solo dos desarrolladores, ha presentado Luminary, un ARPG-lite de fantasía diseñado para jugar en solitario o en cooperativo de hasta tres jugadores, con progresión compartida, exploración, un sistema de combate accesible y un mundo en el que resulta facilísimo sumergirse. Luminary ya está disponible en Acceso Anticipado con soporte para DLSS 4.5 Super Resolution, Multi Frame Generation, DLAA y la tecnología de iluminación Lumen de Unreal Engine 5.

Para saber más acerca de NVIDIA y las tecnologías RTX, los usuarios interesados pueden visitar la página oficial de la compañía.

La entrada NVIDIA anuncia la llegada de nuevos juegos con tecnologías RTX apareció primero en ZIRAN Comunicación.]]>
Gears of War: E-Day abre su beta multijugador, No More Room In Hell 2 y Hell Let Loose: Vietnam llegan con DLSS 4.5 https://www.ziran.es/nota_prensa/gears-of-war-e-day-abre-su-beta-multijugador-no-more-room-in-hell-2-y-hell-let-loose-vietnam-llegan-con-dlss-4-5/ Tue, 18 Aug 2026 09:58:10 +0000 https://www.ziran.es/?post_type=nota_prensa&p=68375 Hoy, la beta multijugador de Gears of War: E-Day se abre a todos los jugadores y No More Room In Hell 2 sale del Acceso Anticipado. Hell Let Loose: Vietnam llega el jueves. Además, Phantom Blade Zero ya se puede reservar antes de su lanzamiento el 29 de octubre. Estas son las principales novedades RTX […]

La entrada Gears of War: E-Day abre su beta multijugador, No More Room In Hell 2 y Hell Let Loose: Vietnam llegan con DLSS 4.5 apareció primero en ZIRAN Comunicación.]]>

Hoy, la beta multijugador de Gears of War: E-Day se abre a todos los jugadores y No More Room In Hell 2 sale del Acceso Anticipado. Hell Let Loose: Vietnam llega el jueves. Además, Phantom Blade Zero ya se puede reservar antes de su lanzamiento el 29 de octubre.

Estas son las principales novedades RTX de esta semana:

Gears of War E-Day: Hoy, The Coalition ha abierto la beta multijugador de Gears of War: E-Day a todos los jugadores, con acceso gratuito hasta el 17 de agosto. La beta incluye el nuevo modo Horda: Asedio, además de un modo PvP Versus 4 contra 4 perfeccionado. En PC, los jugadores con GeForce RTX pueden activar DLSS Super Resolution y NVIDIA Reflex, mientras que el juego completo llegará con el conjunto completo de tecnologías DLSS 4.5.

Phantom Blade Zero: Tras ser acusado de la muerte de su maestro y quedar con el corazón destrozado, Soul dispone de sesenta y seis días de vida en Phantom Blade Zero, el próximo juego de acción y rol de S-GAME, que ha confirmado que el juego se lanzará el 29 de octubre y que ya están disponibles las reservas en Steam y Epic Games Store. En PCs y portátiles GeForce RTX, Phantom Blade Zero contará con DLSS 4.5 Super Resolution y Multi Frame Generation, además de reflejos, sombras y cáusticas trazados por rayos exclusivos de PC, acelerados por los núcleos Ray Tracing.

Hell Let Loose: Vietnam: Hoy, Hell Let Loose: Vietnam, de Expression Games y Team17, se lanza con compatibilidad con DLSS 4.5 Super Resolution, ofreciendo a los jugadores con GeForce RTX una mayor calidad de imagen y tasas de fotogramas más altas. Los usuarios de GeForce RTX Serie 50 también pueden activar Dynamic Multi Frame Generation a través de la aplicación de NVIDIA.

No More Room In Hell 2: Esta semana, No More Room In Hell 2, de Torn Banner Studios, ha salido oficialmente del Acceso Anticipado con la incorporación del Modo Supervivencia, un sexto mapa de objetivos, Modo Solo y mucho más. Con la actualización de lanzamiento, todo el conjunto se ha actualizado a DLSS 4.5, mejorando la calidad de imagen. También se ha incorporado Dynamic Multi Frame Generation, que permite alcanzar niveles de rendimiento aún mayores en GPUs GeForce RTX Serie 50.

GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.

Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

La entrada Gears of War: E-Day abre su beta multijugador, No More Room In Hell 2 y Hell Let Loose: Vietnam llegan con DLSS 4.5 apareció primero en ZIRAN Comunicación.]]>
GeForce NOW sube de nivel en Linux, Chromebooks y mucho más https://www.ziran.es/nota_prensa/geforce-now-sube-de-nivel-en-linux-chromebooks-y-mucho-mas/ Tue, 18 Aug 2026 09:48:14 +0000 https://www.ziran.es/?post_type=nota_prensa&p=68370 El cloud gaming es ahora más fluido y nueve juegos se incorporan esta semana a la nube. La aplicación nativa de GeForce NOW para Linux sale oficialmente de la fase beta. GeForce NOW también incorpora nuevas optimizaciones en la nube que hacen que la Generación de Fotogramas resulte aún más fluida y responda mejor durante […]

La entrada GeForce NOW sube de nivel en Linux, Chromebooks y mucho más apareció primero en ZIRAN Comunicación.]]>

El cloud gaming es ahora más fluido y nueve juegos se incorporan esta semana a la nube.

La aplicación nativa de GeForce NOW para Linux sale oficialmente de la fase beta. GeForce NOW también incorpora nuevas optimizaciones en la nube que hacen que la Generación de Fotogramas resulte aún más fluida y responda mejor durante el streaming. Además, los miembros Performance disfrutarán de mayores tasas de fotogramas en juegos exigentes gracias a un ajuste del rendimiento de la CPU.

Además, descubre cómo GeForce NOW puede añadir gaming de alto rendimiento con GeForce RTX a los Chromebooks que los estudiantes ya utilizan para estudiar, y cómo los nuevos propietarios que cumplan los requisitos pueden beneficiarse de Chromebook Fast Pass.

Todo ello se traduce en más formas de pasar de las tareas a la aventura desde prácticamente cualquier dispositivo.

Lo único que queda por hacer es decidir a qué jugar. Esta semana, nueve nuevos juegos se incorporan al catálogo de GeForce NOW.

La nube suma puntos extra

GeForce NOW no deja de mejorar.
La aplicación nativa para Linux de GeForce NOW ha salido oficialmente de la fase beta. Desarrollada a partir de meses de comentarios de la comunidad, esta versión se centra en el rendimiento, la estabilidad y el acabado, y sigue siendo compatible con Ubuntu 24.04 y versiones posteriores. Un nuevo repositorio Flatpak facilita aún más la puesta en marcha y la recepción de futuras actualizaciones. Visita la página de descarga para obtener más información e instrucciones.
La nube se encarga del renderizado, por lo que los jugadores de Linux pueden disfrutar del último rendimiento de GeForce RTX manteniendo su configuración preferida, sin necesidad de actualizar el hardware local, enfrentarse a problemas de compatibilidad ni recurrir a soluciones complicadas.
El juego fluido merece matrícula de honor.
GeForce NOW también ha optimizado la Generación de Fotogramas de DLSS en la nube, reduciendo la latencia y haciendo que los juegos respondan mejor. Las mejoras se aprecian especialmente al hacer streaming a 60 o 120 fotogramas por segundo en 1440p y 4K, haciendo que cada movimiento del ratón y cada giro de cámara se sientan más inmediatos.
Los miembros Performance también disfrutarán de optimizaciones adicionales del software de los servidores para mejorar las tasas de fotogramas en determinados juegos que hacen un uso intensivo de la CPU. Esto ayuda a que los títulos más exigentes funcionen con mayor fluidez y ofrece una experiencia de juego aún mejor. La mejora aplicada en la nube se activa automáticamente, sin que los miembros tengan que instalar ni configurar nada y sin coste adicional.
Del modo clase al modo juego
Los Chromebooks que ya van en las mochilas pueden convertirse en auténticas máquinas de gaming para PC, y GeForce NOW aporta un extra a los dispositivos que se utilizan a diario para estudiar.
Los Chromebooks que se utilizan para asistir a clases, realizar trabajos en grupo y gestionar pestañas del navegador pueden transformarse en PCs gaming de alto rendimiento con GeForce RTX en tan solo unos clics.
Cuando terminen las clases, basta con abrir un navegador o una aplicación compatible para hacer streaming de más de 2.000 juegos de PC compatibles de las bibliotecas existentes, mientras la nube se encarga de todo el trabajo pesado. La misma flexibilidad se extiende a Mac, dispositivos Surface, portátiles convencionales, Steam Deck y dispositivos móviles.
Además, los nuevos propietarios de Chromebook y Chromebook+ que cumplan los requisitos pueden disfrutar de un año de GeForce NOW sin coste con Chromebook Fast Pass, con acceso prioritario y sin anuncios.
Haz streaming de juegos de PC. El mismo dispositivo.
los miembros podrán encontrar esta semana los siguientes nuevos juegos disponibles mediante streaming:
Car Wash Simulator (Nuevo lanzamiento en Steam, 10 de agosto)
Pax Autocratica (Nuevo lanzamiento en Steam, 10 de agosto)
Clawed (Nuevo lanzamiento en Steam, 13 de agosto)
Hell Let Loose: Vietnam (Nuevo lanzamiento en Steam, 13 de agosto)
Sandustry (Nuevo lanzamiento en Steam y Xbox, 13 de agosto)
Cat Mail Co. (Steam)
Misery (Steam)
Monster Hunter Wilds Prologue Demo (Steam)
Pratfall (Steam)
Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

 

 

La entrada GeForce NOW sube de nivel en Linux, Chromebooks y mucho más apareció primero en ZIRAN Comunicación.]]>
GEFORCE NOW REVOLUCIONA AGOSTO CON 26 NUEVOS JUEGOS Y SE PRESENTA EN QUAKECON https://www.ziran.es/nota_prensa/geforce-now-revoluciona-agosto-con-26-nuevos-juegos-y-se-presenta-en-quakecon/ Mon, 10 Aug 2026 10:14:05 +0000 https://www.ziran.es/?post_type=nota_prensa&p=67951 NVIDIA aterriza en el evento de Texas incorporando ocho títulos esta misma semana a su servicio de juego en la nube. Agosto ya está aquí y llega cargado de novedades para los usuarios de GeForce NOW, que recibirán 26 nuevos títulos a lo largo del mes. Los jugadores ya pueden tomar el mando en World […]

La entrada GEFORCE NOW REVOLUCIONA AGOSTO CON 26 NUEVOS JUEGOS Y SE PRESENTA EN QUAKECON apareció primero en ZIRAN Comunicación.]]>

NVIDIA aterriza en el evento de Texas incorporando ocho títulos esta misma semana a su servicio de juego en la nube.

Agosto ya está aquí y llega cargado de novedades para los usuarios de GeForce NOW, que recibirán 26 nuevos títulos a lo largo del mes. Los jugadores ya pueden tomar el mando en World of Warships: Legends y descubrir los 8 juegos que se suman al catálogo esta misma semana.
Además, GeForce NOW estará presente durante estos días en la feria de videojuegos QuakeCon en Grapevine (Texas), ofreciendo a los asistentes experiencias de juego directo en la nube.
Presencia destacada en QuakeCon
En el estand de NVIDIA en QuakeCon, los asistentes podrán probar de primera mano la experiencia de juego en la nube con el nivel de rendimiento Ultimate impulsado por tarjetas GeForce RTX 5080. Las demostraciones mostrarán un apartado visual con resoluciones de hasta 5K a 120 fotogramas por segundo en pantallas ultrapanorámicas, así como una ejecución fluida en dispositivos portátiles como Lenovo Legion Go S.
Los visitantes comprobarán cómo miles de títulos de PC, incluidos los grandes éxitos de Bethesda, se ejecutan en portátiles, Mac, consolas portátiles, dispositivos móviles y Smart TVs, permitiendo reanudar la partida en cualquier pantalla compatible. Aquellos usuarios que no puedan acudir al evento tienen la opción de probar el pase diario Ultimate para disfrutar del catálogo de Bethesda desde cualquier dispositivo.
Llegadas de esta semana y lanzamientos para todo el mes
El combate naval free-to-play de World of Warships: Legends desembarca esta semana en GeForce NOW. Los capitanes podrán ponerse al frente de destructores, cruceros y acorazados en batallas multijugador masivas mientras exploran su última actualización, que incluye la campaña Pacific Hammer y una nueva línea de destructores estadounidenses.
Sin necesidad de descargas ni instalaciones previa, la lista completa de títulos disponibles a partir de esta semana incluye:
  • Big Walk (Steam, 4 de agosto)
  • Beacon Pines (Gratis en Epic Games Store, 6 de agosto)
  • Sovereign Tower (Steam, 6 de agosto)
  • Expeditions: Samurai (Steam, 7 de agosto)
  • The Adventures of Elliot: The Millennium Tales (Xbox, Microsoft Store)
  • The Incident at Galley House (Steam)
  • Machine Party (Steam)
  • World of Warships: Legends (Steam)
  • Pax Autocratica (Steam, 10 de agosto)
  • Car Wash Simulator (Steam, 10 de agosto)
  • Clawed (Steam, 13 de agosto)
  • Hell Let Loose: Vietnam (Steam, 13 de agosto)
  • Sandustry (Steam y Xbox, disponible en Game Pass, 13 de agosto)
  • The Sinking City 2 (Steam, 18 de agosto)
  • Mortal Shell II (Steam, 20 de agosto)
  • Gallipoli (Steam, 20 de agosto)
  • Aliens: Fireteam Elite 2 (Steam, 25 de agosto)
  • Resonance: A Plague Tale Legacy (Steam y Xbox, disponible en Game Pass, 27 de agosto)
  • Breathedge 2 (Steam, 30 de agosto)
  • High on Life (Steam)
  • High on Life 2 (Steam y Xbox, disponible en Game Pass)
  • Paradise Killer (Steam)
  • Misery (Steam)
  • Pratfall (Steam)
  • Starvester (Steam)

Adicionales del mes de julio

Junto a los títulos anunciados el mes pasado, 15 juegos más se incorporaron finalmente al catálogo de GeForce NOW durante julio:

Breath of Fire IV, Call of Duty: Black Ops 6 (Ubisoft Connect), CloverPit (Game Pass), Dinoblade, Dino Crisis, Dino Crisis 2, Esports Manager 2026, Funnel Runners, la demo de Granblue Fantasy: Relink – Endless Ragnarok, Halo: Campaign Evolved (Game Pass), la demo de Onimusha: Way of the Sword, Pathogenic, Sudden Attack Zero Point y The Life and Suffering of Prince Jerian.
(Nota: La llegada de Mistfall Hunter se ha pospuesto; los detalles se actualizarán en los próximos GFN Thursday).
GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.
Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.
La entrada GEFORCE NOW REVOLUCIONA AGOSTO CON 26 NUEVOS JUEGOS Y SE PRESENTA EN QUAKECON apareció primero en ZIRAN Comunicación.]]>
NVIDIA ANUNCIA EL ACCESO ANTICIPADO A LA BETA DE GEARS OF WAR: E-DAY CON DLSS, Y SU REGRESO A QUAKECON https://www.ziran.es/nota_prensa/nvidia-anuncia-el-acceso-anticipado-a-la-beta-de-gears-of-war-e-day-con-dlss-y-su-regreso-a-quakecon/ Mon, 10 Aug 2026 10:10:28 +0000 https://www.ziran.es/?post_type=nota_prensa&p=67949 En la antesala de su lanzamiento oficial programado para el 6 de octubre, NVIDIA ha anunciado que los usuarios que hayan reservado Gears of War: E-Day y los suscriptores de PC Game Pass tendrán  acceso anticipado a la Beta Abierta multijugador del título a partir del 6 de agosto. En su versión para PC, la beta incorporará soporte […]

La entrada NVIDIA ANUNCIA EL ACCESO ANTICIPADO A LA BETA DE GEARS OF WAR: E-DAY CON DLSS, Y SU REGRESO A QUAKECON apareció primero en ZIRAN Comunicación.]]>

En la antesala de su lanzamiento oficial programado para el 6 de octubre, NVIDIA ha anunciado que los usuarios que hayan reservado Gears of War: E-Day y los suscriptores de PC Game Pass tendrán  acceso anticipado a la Beta Abierta multijugador del título a partir del 6 de agosto.

En su versión para PC, la beta incorporará soporte para NVIDIA DLSS Super Resolution junto con NVIDIA Reflex, garantizando la máxima calidad de imagen y una tasa de fotogramas fluida durante esta fase de prueba. De cara al lanzamiento final del juego, los usuarios con GPUs GeForce RTX tendrán acceso al conjunto completo de tecnologías DLSS 4.5, lo que acelerará aún más el rendimiento gráfico.

Desarrollado desde cero con Unreal Engine 5 y DirectX 12, Gears of War: E-Day ofrece un fidelidad gráfica sin precedentes:

MegaLights: Permite el renderizado eficiente de sombras por trazado de rayos (Ray Tracing) procedentes de hasta 100 fuentes de luz dinámicas.
Lumen: Habilita iluminación global por trazado de rayos y sombreado de oclusión ambiental.
Nanite: Incrementa el detalle y la fidelidad de los objetos en pantalla hasta 100 veces en comparación con Gears 5.
NVIDIA regresa a QuakeCon (del 6 al 9 de agosto)
NVIDIA también estará presente en QuakeCon con una completa agenda de actividades e iniciativas para la comunidad:
Desafíos de Gaming: Los asistentes podrán competir en los retos de juego de Quake III Arena RTX Remix y DOOM: The Dark Ages | Revelations para optar a ganar tarjetas gráficas GeForce RTX 5070 Founders Edition, así como regalos exclusivos de la marca.
GeForce Trading Cards: Se distribuirá un paquete limitado de tarjetas coleccionables que repasan 14 de los momentos más icónicos del gaming en GeForce. Para completarla, los asistentes deberán intercambiarlas en el evento hasta agotar existencias.
Concurso Oficial de Modding en la LAN BYOC: GeForce Garage volverá a ser el anfitrión del concurso oficial de mods de QuakeCon. Se premiará a los mejores creadores de PCs modificados y sistemas artesanales con tarjetas gráficas GeForce RTX Serie 50, tarjetas de regalo para refrigeración líquida Bitspower y disipadores AIO de TRYX. El ganador del gran premio viajará a la sede central de NVIDIA en California para protagonizar un episodio especial de Rig Spotlight.
Enlaces de interés:
GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.
Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.
La entrada NVIDIA ANUNCIA EL ACCESO ANTICIPADO A LA BETA DE GEARS OF WAR: E-DAY CON DLSS, Y SU REGRESO A QUAKECON apareció primero en ZIRAN Comunicación.]]>
GeForce NOW se pone al rojo vivo con Halo: Campaign Evolved https://www.ziran.es/nota_prensa/geforce-now-se-pone-al-rojo-vivo-con-halo-campaign-evolved/ Mon, 10 Aug 2026 09:36:56 +0000 https://www.ziran.es/?post_type=nota_prensa&p=67933 NVIDIA ha anunciado las novedades que llegarán esta semana a GeForce NOW, la plataforma de videojuegos en la nube. Durante estos días, 8 juegos se sumarán a la extensa biblioteca del servicio, entre los que destacan títulos como Halo: Campaign Evolved, Mistfall Hunter o Corsair Cove. Para los que, en estas vacaciones, quieran resguardarse del calor y disfrutar del […]

La entrada GeForce NOW se pone al rojo vivo con Halo: Campaign Evolved apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha anunciado las novedades que llegarán esta semana a GeForce NOW, la plataforma de videojuegos en la nube. Durante estos días, 8 juegos se sumarán a la extensa biblioteca del servicio, entre los que destacan títulos como Halo: Campaign EvolvedMistfall Hunter Corsair Cove.

Para los que, en estas vacaciones, quieran resguardarse del calor y disfrutar del mejor gaming AAA, Halo: Campaign Evolved será su mejor aliado. Los miembros con una cuenta Ultimate podrán experimentar el icónico regreso del Jefe Maestro con un rendimiento propio de la gama GeForce RTX 5080 desde la nube, aprovechando todas las virtudes de las tecnologías NVIDIA DLSStrazado de rayos y NVIDIA Reflex que, combinadas, son capaces de ofrecer una experiencia insuperable, con una jugabilidad fluida y con una respuesta ultrarrápida en casi cualquier dispositivo.

Aquellos que no sean de lanzarse a la piscina a la primera de cambio, podrán aprovechar el pase de un día para experimentar las ventajas de las cuentas premium. Y, si la experiencia les resulta convincente, el coste del pase se descontará de la primera suscripción a GeForce NOW.

A continuación, se detalla la lista completa de juegos que se añadirán a la biblioteca esta semana:

  • Halo: Campaign Evolved (Nuevo en Steam y Xbox, Game Pass)
  • Mistfall Hunter (Nuevo en Steam)
  • Call of Duty: Black Ops 6 (Nuevo en Ubisoft Connect)
  • Sudden Attack Zero Point (Nuevo en Steam)
  • The Ranchers (Nuevo en Steam)
  • Corsair Cove (Nuevo en Steam y Xbox, Game Pass)
  • Funnel Runners (Steam)
  • Pathogenic (Steam)

GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.

Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

La entrada GeForce NOW se pone al rojo vivo con Halo: Campaign Evolved apareció primero en ZIRAN Comunicación.]]>
Halo: Campaign Evolved llega hoy con NVIDIA DLSS, un nuevo Game Ready Driver y nuevas recompensas GeForce https://www.ziran.es/nota_prensa/halo-campaign-evolved-llega-hoy-con-nvidia-dlss-un-nuevo-game-ready-driver-y-nuevas-recompensas-geforce/ Tue, 28 Jul 2026 19:08:48 +0000 https://www.ziran.es/?post_type=nota_prensa&p=67586 NVIDIA ha anunciado los próximos juegos que llegarán con tecnologías RTX. Entre las principales novedades, destacan Halo: Campaign Evolved, que se lanzará hoy con soporte para DLSS, seguido de Mistfall Hunter, que lo hará el miércoles y Corsair Cove, que se estrenará el viernes. Además, The Mound: Omen of Cthulhu, Palworld 1.0 y Killing Floor 3 – Operation: Shadow Hunter ya están disponibles […]

La entrada Halo: Campaign Evolved llega hoy con NVIDIA DLSS, un nuevo Game Ready Driver y nuevas recompensas GeForce apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha anunciado los próximos juegos que llegarán con tecnologías RTX. Entre las principales novedades, destacan Halo: Campaign Evolved, que se lanzará hoy con soporte para DLSS, seguido de Mistfall Hunter, que lo hará el miércoles y Corsair Cove, que se estrenará el viernes. Además, The Mound: Omen of CthulhuPalworld 1.0 Killing Floor 3 – Operation: Shadow Hunter ya están disponibles y ofrecen la posibilidad de actualizar a DLSS 4.5 a través de NVIDIA app.

NVIDIA también ha anunciado la publicación de un nuevo driver GeForce Game Ready que optimiza los sistemas para Halo: Campaign Evolved, la beta multijugador de Gears of War: E-Day y Mistfall Hunter, garantizando la mejor experiencia posible desde el primer día.

Además, a través de la iniciativa GeForce Summer Nights, los usuarios tendrán la oportunidad de ganar una clave de juego de CONTROL Resonant y una GPU GeForce RTX Founders Edition personalizada. Con su lanzamiento programado para el 24 de septiembre con DLSS 4.5 y path tracing, lo nuevo de Remedy Entertainment, CONTROL Resonant, vuelve a elevar el listón de la fidelidad gráfica apostando por un combate cuerpo a cuerpo sobrenatural con un nuevo protagonista: Dylan Faden, hermano de Jesse, la protagonista de la entrega original. Para celebrar la inminente llegada del título, NVIDIA sorteará códigos de reserva del juego, una tarjeta gráfica GeForce RTX 5080 Founders Edition con un diseño único inspirado en el juego y mucho más. Para optar al premio, los jugadores deberán responder a las publicaciones señaladas en las redes sociales de la compañía y, por supuesto, seguir la retransmisión de Jacob el 31 de julio de 22:00 a 24:00 en horario peninsular (CEST).

Por otra parte, NVIDIA ha querido destacar que GeForce Rewards ofrecerá suscripciones de 3 meses a Discord Nitro hpor tiempo limitado. Para conseguir una, los usuarios que dispongan de un PC o portátil con una tarjeta gráfica GeForce GTX Serie 10 o superior podrán reclamarla accediendo en NVIDIA app. Las unidades son limitadas y se entregarán por orden de llegada.

A continuación, NVIDIA ha querido ofrecer un repaso detallado a las novedades RTX de esta semana:

  • Hoy se lanza oficialmente Halo: Campaign Evolved con DLSS Super Resolution, Frame Generation y NVIDIA Reflex. Los usuarios también tendrán la posibilidad de actualizar el juego a DLSS 4.5 Dynamic Multi Frame Generation y al modelo de Super Resolution más reciente a través de NVIDIA app. El nuevo driver GeForce Game Ready ofrece optimizaciones para disfrutar de la mejor versión del título.
  • El 29 de julio se lanzará Mistfall Hunter, de Bellring Games, con soporte para DLSS Super Resolution, Multi Frame Generation, Dynamic Multi Frame Generation, NVIDIA Reflex y reflejos y sombras con trazado de rayos.
  • El 31 de julio, el city builder de temática pirata de Limbic Entertainment y Hooded Horse, Corsair Cove, se lanzará con DLSS 4.5 Super Resolution, Frame Generation, Multi Frame Generation (hasta 4X), NVIDIA Reflex y NVIDIA DLAA. Los usuarios con una GPU GeForce RTX Serie 50 podrán disfrutar del modo Dynamic Multi Frame Generation de hasta 6X, activándolo a través de NVIDIA app.
  • La semana pasada se lanzó el juego de terror cooperativo de NACON y ACE Team, The Mound: Omen of Cthulhu, compatible con DLSS Super Resolution, Multi Frame Generation y NVIDIA Reflex. A través de NVIDIA app, los jugadores con una tarjeta gráfica GeForce RTX ya pueden actualizar el título a DLSS 4.5 con Dynamic Multi Frame Generation y disfrutar del modelo de Super Resolution más reciente para obtener un rendimiento y una calidad de imagen aún mayores.
  • El FPS de acción y terror cooperativo de Tripwire Interactive, Killing Floor 3, acaba de recibir su actualización Operation: Shadow Hunter, que incluye el mapa Oil Rig, la clase Gunslinger , nuevas armas, un nuevo jefe, mejoras de calidad de vida y un nivel de dificultad superior. Los jugadores con gráficas GeForce RTX pueden acelerar el rendimiento con DLSS Super Resolution y Multi Frame Generation. Además, mediante NVIDIA app, se puede actualizar Super Resolution a sus versiones más recientes, así como activar Dynamic Multi Frame Generation hasta 6X en las GPU GeForce RTX Serie 50.
  • Palworld, el exitoso juego de supervivencia de Pocketpair que está en boca de todos, ya se puede actualizar al último modelo de DLSS 4.5 Super Resolution a través de NVIDIA app. Los jugadores con una GeForce RTX Serie 50 también pueden actualizar el título a DLSS Dynamic Multi Frame Generation para alcanzar tasas de fotogramas aún más elevadas.
  • De cara al lanzamiento de Gears of War: E-Day el 6 de octubre, quienes hayan reservado el juego y los suscriptores de PC Game Pass podrán acceder a la beta abierta multijugador a partir del 6 de agosto. La beta para PC incluye DLSS Super Resolution y NVIDIA Reflex, mientras que el juego completo llegará al mercado con el paquete completo de tecnologías DLSS 4.5. El nuevo controlador GeForce Game Ready también cuenta con optimizaciones para la beta.
Por último, NVIDIA se ha reunido con el equipo responsable del motor RE ENGINE de Capcom para llevar a cabo una nueva sesión de preguntas y respuestas con los desarrolladores, en la que se profundiza sobre la implementación del trazado de rutas en Resident Evil Requiem y PRAGMATA. La charla aborda el enfoque del equipo en cuanto a iluminación, reflejos y flujos de trabajo de assets, así como la manera en que el trazado de rayos está ayudando a plasmar el estilo visual único de ambos títulos.
La entrada Halo: Campaign Evolved llega hoy con NVIDIA DLSS, un nuevo Game Ready Driver y nuevas recompensas GeForce apareció primero en ZIRAN Comunicación.]]>
GeForce NOW recibe 9 juegos esta semana https://www.ziran.es/nota_prensa/geforce-now-recibe-9-juegos-esta-semana/ Tue, 28 Jul 2026 18:33:24 +0000 https://www.ziran.es/?post_type=nota_prensa&p=67560 NVIDIA ha anunciado los juegos que se sumarán a la biblioteca de GeForce NOW esta semana. La plataforma de videojuegos en la nube permitirá a los usuarios del servicio disfrutar de 9 nuevos títulos, con clásicos como Dino Crisis y Dino Crisis 2, así como lanzamientos como ZeroSpace, The Life and Suffering of Prince Jerian y Carnival Hunt, entre otros. Además, los […]

La entrada GeForce NOW recibe 9 juegos esta semana apareció primero en ZIRAN Comunicación.]]>

NVIDIA ha anunciado los juegos que se sumarán a la biblioteca de GeForce NOW esta semana. La plataforma de videojuegos en la nube permitirá a los usuarios del servicio disfrutar de 9 nuevos títulos, con clásicos como Dino Crisis y Dino Crisis 2, así como lanzamientos como ZeroSpaceThe Life and Suffering of Prince Jerian y Carnival Hunt, entre otros.

Además, los suscriptores de GeForce NOW podrán acceder a las actualizaciones de algunos de los títulos más populares sin necesidad de esperar a tiempos de descarga ni de llenar su disco duro con nuevos contenidos. En esta ocasión, destacan la expansión de Path of ExilePath of Exile: Curse of the Allflame, y la Temporada 4 de Battlefield 6.

También, a partir de esta semana, los fans de Capcom tendrán la ocasión de rememorar grandes clásicos del pasado, como Breath of Fire IVDino Crisis Dino Crisis 2. Por otro lado, los amantes de Halo podrán disfrutar desde la nube de Halo: Campaign Evolved Advanced Access.

Ya sea para disfrutar de las últimas novedades de sus juegos favoritos o para descubrir algo totalmente nuevo, los miembros pueden explorar miles de títulos de PC en el catálogo de GeForce NOW desde prácticamente cualquier dispositivo (PC, Mac, consolas portátiles, móviles y más), sin tener que preocuparse por el espacio de almacenamiento ni por actualizar el hardware.

Esta semana, la biblioteca de GeForce NOW recibirá los siguientes títulos:

  • ZeroSpace (Nuevo en Steam)
  • The Life and Suffering of Prince Jerian (Nuevo en Steam)
  • The Planet Crafter (Nuevo en Xbox, Game Pass)
  • Carnival Hunt (Nuevo en Steam)
  • Dinoblade (Nuevo en Steam)
  • Breath of Fire IV (Steam)
  • CloverPit (Xbox, Game Pass)
  • Dino Crisis (Steam)
  • Dino Crisis 2 (Steam)

GeForce NOW es la plataforma de videojuegos en la nube de NVIDIA. Permite conectarse a las bibliotecas de las principales tiendas de juegos en línea, así como disfrutar de los juegos disponibles a través de PC Game Pass. Los miembros de GeForce NOW pueden disfrutar de sus aventuras a través de una gran variedad de dispositivos, incluyendo televisores con NVIDIA SHIELD, portátiles poco potentes, Mac, Chromebook, dispositivos portátiles como Steam Deck y cascos de realidad virtual.

Para más información acerca de GeForce NOW y las tecnologías más punteras para gaming de NVIDIA, los usuarios interesados pueden visitar la página oficial de la compañía.

La entrada GeForce NOW recibe 9 juegos esta semana apareció primero en ZIRAN Comunicación.]]>