HTTP-запрос из JavaScript с использованием необработанных сообщений, включая заголовки
Я знаю, как сделать HTTP-запрос к моему REST API из javascript, используя jQuery или XMLHttpRequest. Сейчас я хочу сделать запрос без установки свойств для значений заголовка. Сообщение HTTP-запроса состоит из:
- Строка запроса, такая как GET /images/logo.png HTTP/1.1, которая запрашивает ресурс с именем /images/logo.png с сервера
- Заголовки, такие как Accept-Language: en
- Пустая строка
- Необязательное тело сообщения
Запрос к моему API должен выглядеть примерно так:
GET /myapi/myresource/1234 HTTP/1.1
Host: localhost:51127
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/csv
Authorization: Basic <base64 encoded credentials>
Я хотел бы открыть соединение с localhost:51127, отправить вышеприведенный текст и получить ответ. Это возможно в JavaScript?
Обновление: я знаю, как установить заголовки. Я просто хочу сделать это по-другому. Существует множество способов "создать" запрос, включая заголовки, и отправить его. Я просто хочу построить его вручную.
3 ответа
В Javascript нет поддержки сокетов. Вы можете создавать только HTTP-запросы, используя XMLHTTPRequest
обертка или, возможно, обертки для этого, такие как jQuery.ajax
, Это по разным причинам, главным образом, для безопасности.
Вы можете получить экземпляр объекта HmlHttpRequest и использовать setRequestHeader.
В jQuery есть обработчик beforeSend, который вы можете установить для получения реального объекта hxr.
$.ajax({
beforeSend: function(xhr){
xhr.setRequestHeader("name","value");
}
...
})
Чтобы развить ответ lonesomeday, вот как это сделать на самом деле.
function rawRequest(txt,cb) {
let x = new XMLHttpRequest(),
lines = txt.split("\n"),
methods = [
"GET",
"POST",
"PATCH",
"PUT",
"DELETE",
"HEAD",
"OPTIONS"
],
host, path, method, version, body = "", headers = {}
lines.forEach((x, i) => {
if(!x.includes(":")) {
let ind;
methods.forEach(m => {
let tmpIndex = x.indexOf(m);
if(tmpIndex > -1) {
if(!method) {
ind = tmpIndex;
let words = x.split(" ");
method = x.substring(
tmpIndex,
tmpIndex +
m.length
);
method = method && method.trim();
path = words.find((y, k) =>
y[0] === "/"
)
path = path && path.trim();
version = (
x
.replace(method, "")
.replace(path, "")
).trim();
}
}
});
} else {
let indexOfSemiColon = x.indexOf(":");
if(
indexOfSemiColon > 0 &&
indexOfSemiColon < x.length - 1
) {
let key = x.substring(
0,
indexOfSemiColon
).trim(),
value = x.substring(
indexOfSemiColon + 1
).trim();
headers[key] = value;
if(key.toLowerCase() == "host") {
host = value
}
}
}
});
let inds = []
txt.split(/\r?\n/).forEach((x,i)=>
x === ""
&& inds.push(i)
)
let afterTwoLineBreaksIndex;
inds.forEach((x,i) => {
if(
i < inds.length - 2 &&
inds[i] === "" &&
inds[i + 1] === ""
) {
afterTwoLineBreaksIndex = i + 1;
}
});
if(afterTwoLineBreaksIndex) {
body = txt.substring(
afterTwoLineBreaksIndex
)
}
x.onreadystatechange = () => {
if(x.readyState == 4 && x.status == 200) {
if(cb) cb(x.response);
}
}
if(host && path && method) {
x.open(
method,
"http://" //don't know how to differentiate between http & https, if some1 could help out would be greate
+ host
+ path
);
for(let k in headers) {
x.setRequestHeader(k, headers[k]);
}
x.send(body);
}
return {
headers,
body,
method,
host,
path,
version
} //for testing just return all the values we found
}
console.log(
rawRequest(`
GET /search?q=test HTTP/2
Host: www.bing.com
User-Agent: curl/7.54.0
Accept: */*`
),
rawRequest(`
GET /foo/bar HTTP/1.1
Host: example.org
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; fr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: */*
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Referer: http://example.org/test
Cookie: foo=bar; lorem=ipsum;
`),
rawRequest(`
GET /myapi/myresource/1234 HTTP/1.1
Host: localhost:51127
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/csv
Authorization: Basic <base64 encoded credentials>
`)
)
Пришел сюда в поисках того же. Я думаю, что было бы возможно построить что-то, что берет необработанный текст запроса и анализирует его в объект xmlHttpRequest, помещая заголовки и т. Д. В правильные свойства. Просьба прокомментировать ссылку, если что-то подобное уже существует. В принципе, если jQuery имеет функцию BuildRequestFromRaw(текст), это было бы замечательно.