¿Por qué no funciona HttpClient BaseAddress?

Resuelto Timothy Shields asked hace 10 años • 5 respuestas

Considere el siguiente código, donde BaseAddressdefine una ruta de URI parcial.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync("/resource/7");
}

Espero que esto realice una GETsolicitud a http://something.com/api/resource/7. Pero no es así.

Después de buscar un poco, encuentro esta pregunta y respuesta: HttpClient con BaseAddress . La sugerencia es colocarlo /al final del BaseAddress.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("/resource/7");
}

Todavía no funciona. Aquí está la documentación: HttpClient.BaseAddress ¿Qué está pasando aquí?

Timothy Shields avatar May 03 '14 06:05 Timothy Shields
Aceptado

Resulta que, de las cuatro permutaciones posibles para incluir o excluir barras diagonales finales o iniciales en el BaseAddressURI relativo pasado al GetAsyncmétodo (o cualquier otro método) HttpClient, solo una permutación funciona. Debe colocar una barra al final de BaseAddressy no debe colocar una barra al principio de su URI relativo, como en el siguiente ejemplo.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("resource/7");
}

Aunque respondí mi propia pregunta, pensé en aportar la solución aquí ya que, nuevamente, este comportamiento hostil no está documentado. Mi colega y yo pasamos la mayor parte del día intentando solucionar un problema que en última instancia fue causado por esta rareza de HttpClient.

Timothy Shields avatar May 02 '2014 23:05 Timothy Shields

La resolución de referencia se describe en RFC 3986 Identificador uniforme de recursos (URI): sintaxis genérica . Y así es exactamente como se supone que debe funcionar. Para preservar la ruta del URI base, debe agregar una barra al final del URI base y eliminar la barra al comienzo del URI relativo.

Si el URI base contiene una ruta que no está vacía, el procedimiento de fusión descarta su última parte (después de la última /). Sección relevante :

5.2.3. Fusionar rutas

El pseudocódigo anterior se refiere a una rutina de "fusión" para fusionar una referencia de ruta relativa con la ruta del URI base. Esto se consigue de la siguiente manera:

  • Si el URI base tiene un componente de autoridad definido y una ruta vacía, entonces devuelve una cadena que consta de "/" concatenada con la ruta de referencia; de lo contrario

  • devuelve una cadena que consta del componente de ruta de referencia agregado a todos menos al último segmento de la ruta del URI base (es decir, excluyendo cualquier carácter después del "/" más a la derecha en la ruta del URI base, o excluyendo toda la ruta del URI base si no contiene ningún carácter "/").

Si el URI relativo comienza con una barra diagonal, se denomina URI relativo de ruta absoluta. En este caso, el procedimiento de fusión ignora todas las rutas de URI base. Para más información consulte 5.2.2. Transformar sección de referencias.

Lionia Vasilev avatar Oct 30 '2017 16:10 Lionia Vasilev

si está utilizando httpClient. SendAsync () no hay sobrecarga de cadenas para proporcionar Uris relativos como las sobrecargas para Get u otros métodos específicos de verbos.

Pero puedes crear un Uri relativo dando UriKind.Relative como segundo parámetro.

var httpRequestMessage = new HttpRequestMessage
{
    Method = httpMethod,
    RequestUri = new Uri(relativeRequestUri, UriKind.Relative),
    Content = content
};

using var httpClient = HttpClientFactory.CreateClient("XClient");
var response = await httpClient.SendAsync(httpRequestMessage);
var responseText = await response.Content.ReadAsStringAsync();
Iman avatar Jun 25 '2021 14:06 Iman