• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

panates / opra / 29494915195

16 Jul 2026 11:33AM UTC coverage: 83.024% (+0.4%) from 82.653%
29494915195

push

github

erayhanoglu
1.29.1

4118 of 5238 branches covered (78.62%)

Branch coverage included in aggregate %.

34348 of 41093 relevant lines covered (83.59%)

239.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.03
/packages/http/src/impl/http-request.host.ts
1
/*
1✔
2
  Some parts of this file contains codes from open source express library
1✔
3
  https://github.com/expressjs
1✔
4
 */
1✔
5
import typeIs from '@browsery/type-is';
1✔
6
import accepts from 'accepts';
1✔
7
import fresh from 'fresh';
1✔
8
import parseRange from 'range-parser';
1✔
9
import type { HttpRequest } from '../interfaces/http-request.interface.js';
1✔
10
import { BodyReader } from '../utils/body-reader.js';
1✔
11

1✔
12
export interface HttpRequestHost extends HttpRequest {}
1!
13
const ENCODING_PATTERN = /encoding=([^;]+)/;
4✔
14

4✔
15
export class HttpRequestHost {
4✔
16
  body?: any;
4✔
17

4✔
18
  get protocol(): string {
4!
19
    const proto = this.header('X-Forwarded-Proto') || 'http';
1✔
20
    const index = proto.indexOf(',');
2✔
21
    return index !== -1 ? proto.substring(0, index).trim() : proto.trim();
1✔
22
  }
3✔
23

3✔
24
  get secure(): boolean {
3✔
25
    return this.protocol === 'https';
1✔
26
  }
1✔
27

1✔
28
  get hostname(): string | undefined {
3✔
29
    let host = this.get('X-Forwarded-Host');
1✔
30
    if (!host) {
1✔
31
      host = this.get('Host');
1✔
32
    } else if (host.indexOf(',') !== -1) {
1✔
33
      // Note: X-Forwarded-Host is normally only ever a
1✔
34
      //       single value, but this is to be safe.
3✔
35
      host = host.substring(0, host.indexOf(',')).trim();
3!
36
    }
×
37

×
38
    if (host) {
3✔
39
      // IPv6 literal support
3✔
40
      const offset = host[0] === '[' ? host.indexOf(']') + 1 : 0;
3!
41
      const index = host.indexOf(':', offset);
3!
42
      return index !== -1 ? host.substring(0, index) : host;
1✔
43
    }
6✔
44
    return '';
6✔
45
  }
6✔
46

6✔
47
  get fresh(): boolean {
6✔
48
    const method = this.method;
6✔
49
    // GET or HEAD for weak freshness validation only
6!
50
    if (method !== 'GET' && method !== 'HEAD') return false;
6✔
51
    const status = this.res?.statusCode;
6✔
52
    // 2xx or 304 as per rfc2616 14.26
6!
53
    if ((status >= 200 && status < 300) || status === 304) {
×
54
      return fresh(this.headers, {
×
55
        etag: this.res.getHeader('ETag'),
×
56
        'last-modified': this.res.getHeader('Last-Modified'),
6✔
57
      });
6✔
58
    }
1✔
59
    return false;
1✔
60
  }
×
61

×
62
  get xhr(): boolean {
×
63
    const val = this.get('X-Requested-With') || '';
×
64
    return val.toLowerCase() === 'xmlhttprequest';
1✔
65
  }
288✔
66

288✔
67
  header(name: string): any {
288✔
68
    name = name.toLowerCase();
288✔
69
    const headers = this.headers;
288✔
70
    switch (name) {
288!
71
      case 'referer':
×
72
        return headers.referer || headers.referrer;
288✔
73
      case 'referrer':
288!
74
        return headers.referrer || headers.referer;
×
75
      default:
288✔
76
        return headers[name];
288✔
77
    }
288✔
78
  }
288✔
79

288✔
80
  get(name: string): any {
1✔
81
    return this.header(name);
22✔
82
  }
22✔
83

22✔
84
  accepts(...types: any): any {
1✔
85
    const accept = accepts(this as any);
4✔
86
    return accept.types.call(accept, ...types);
4✔
87
  }
4✔
88

4✔
89
  acceptsCharsets(...charsets: any) {
1✔
90
    const accept = accepts(this as any);
3✔
91
    return accept.charsets.call(accept, ...charsets) as any;
3✔
92
  }
3✔
93

3✔
94
  acceptsEncodings(...encoding: any): any {
1✔
95
    const accept = accepts(this as any);
4✔
96
    // eslint-disable-next-line prefer-spread
4✔
97
    return accept.encodings.apply(accept, encoding);
4✔
98
  }
4✔
99

4✔
100
  acceptsLanguages(...lang: any): any {
1✔
101
    const accept = accepts(this as any);
2✔
102
    // eslint-disable-next-line prefer-spread
2✔
103
    return accept.languages.apply(accept, lang);
2✔
104
  }
2✔
105

1✔
106
  characterEncoding(): string | undefined {
1✔
107
    const contentType = this.header('content-type');
60✔
108
    return contentType ? ENCODING_PATTERN.exec(contentType)?.[1] : undefined;
1!
109
  }
140✔
110

140✔
111
  is(type: string | string[], ...otherTypes: string[]): string | false | null {
140✔
112
    const types = Array.isArray(type) ? type : [type];
140✔
113
    if (otherTypes.length) types.push(...otherTypes);
140✔
114
    const contentType = this.header('content-type');
140✔
115
    return contentType ? typeIs.is(contentType as any, types) : null;
1!
116
  }
1✔
117

1✔
118
  range(size: number, options) {
1✔
119
    const range = this.header('range');
1!
120
    if (!range) return;
1✔
121
    return parseRange(size, range, options);
1✔
122
  }
61✔
123

61✔
124
  async readBody(
61✔
125
    options: BodyReader.Options,
61✔
126
  ): Promise<string | Buffer | undefined> {
61✔
127
    if (this.body === undefined)
61✔
128
      this.body = await BodyReader.read(this, options);
1✔
129
    return this.body;
1✔
130
  }
1✔
131
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc