61 lines
2.5 KiB
Go
61 lines
2.5 KiB
Go
package proxy
|
||
|
||
import (
|
||
"net/http"
|
||
"net/url"
|
||
"strings"
|
||
)
|
||
|
||
// ExtractSessionHeaders сканирует историю в поисках самой свежей записи
|
||
// под заданный host и вытаскивает из неё Cookie/Authorization — типичные
|
||
// заголовки сессии. Используется Spider, чтобы обходить авторизованные
|
||
// зоны сайта без ручного копирования куки: если ты уже походил по сайту
|
||
// руками через браузер с настроенным прокси, краулер сам подхватит ту же
|
||
// сессию.
|
||
//
|
||
// Идёт от конца истории к началу (самые новые записи первыми) — сессия
|
||
// могла обновиться (перелогин, ротация токена), и должна использоваться
|
||
// самая свежая версия, а не первая попавшаяся.
|
||
func ExtractSessionHeaders(entries []Entry, host string) http.Header {
|
||
h := http.Header{}
|
||
for i := len(entries) - 1; i >= 0; i-- {
|
||
e := entries[i]
|
||
u, err := url.Parse(e.URL)
|
||
if err != nil || u.Host != host {
|
||
continue
|
||
}
|
||
|
||
cookie, auth := parseSessionHeadersFromRaw(e.Raw)
|
||
if cookie != "" && h.Get("Cookie") == "" {
|
||
h.Set("Cookie", cookie)
|
||
}
|
||
if auth != "" && h.Get("Authorization") == "" {
|
||
h.Set("Authorization", auth)
|
||
}
|
||
if h.Get("Cookie") != "" && h.Get("Authorization") != "" {
|
||
break // нашли оба — дальше по истории идти незачем
|
||
}
|
||
}
|
||
return h
|
||
}
|
||
|
||
// parseSessionHeadersFromRaw вытаскивает значения заголовков Cookie и
|
||
// Authorization из сырого текста HTTP-запроса (Entry.Raw). Останавливается
|
||
// на первой пустой строке — конец заголовков, начало тела, там эти
|
||
// заголовки заведомо не встретятся, а тело может быть сколь угодно большим.
|
||
func parseSessionHeadersFromRaw(raw string) (cookie, auth string) {
|
||
for _, line := range strings.Split(raw, "\n") {
|
||
line = strings.TrimRight(line, "\r")
|
||
if line == "" {
|
||
break
|
||
}
|
||
lower := strings.ToLower(line)
|
||
switch {
|
||
case strings.HasPrefix(lower, "cookie:"):
|
||
cookie = strings.TrimSpace(line[len("cookie:"):])
|
||
case strings.HasPrefix(lower, "authorization:"):
|
||
auth = strings.TrimSpace(line[len("authorization:"):])
|
||
}
|
||
}
|
||
return cookie, auth
|
||
}
|