-
Notifications
You must be signed in to change notification settings - Fork 594
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(protocol-http): add types for field (#4390)
### Description Adds `Field`, `FieldPosition`, and `Fields` types to `protocol-http`. ### Testing `yarn test:all`
- Loading branch information
1 parent
6b1be0b
commit 688b866
Showing
3 changed files
with
143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { FieldPosition } from "./FieldPosition"; | ||
|
||
export type FieldOptions = { | ||
name: string; | ||
kind?: FieldPosition | ||
values?: string[]; | ||
}; | ||
|
||
/** | ||
* A name-value pair representing a single field | ||
* transmitted in an HTTP Request or Response. | ||
* | ||
* The kind will dictate metadata placement within | ||
* an HTTP message. | ||
* | ||
* All field names are case insensitive and | ||
* case-variance must be treated as equivalent. | ||
* Names MAY be normalized but SHOULD be preserved | ||
* for accuracy during transmission. | ||
*/ | ||
export class Field { | ||
public readonly name: string; | ||
public readonly kind: FieldPosition; | ||
|
||
public values: string[]; | ||
|
||
constructor({ name, kind = FieldPosition.HEADER, values = [] }: FieldOptions) { | ||
this.name = name; | ||
this.kind = kind; | ||
this.values = values; | ||
} | ||
|
||
/** | ||
* Appends a value to the field. | ||
* | ||
* @param value The value to append. | ||
*/ | ||
public add(value: string): void { | ||
this.values.push(value); | ||
} | ||
|
||
/** | ||
* Overwrite existing field values. | ||
* | ||
* @param values The new field values. | ||
*/ | ||
public set(values: string[]): void { | ||
this.values = values; | ||
} | ||
|
||
/** | ||
* Remove all matching entries from list. | ||
* | ||
* @param value Value to remove. | ||
*/ | ||
public remove(value: string): void { | ||
this.values = this.values.filter((v) => v !== value); | ||
} | ||
|
||
/** | ||
* Get comma-delimited string. | ||
* | ||
* @returns String representation of {@link Field}. | ||
*/ | ||
public toString(): string { | ||
// Values with spaces or commas MUST be double-quoted | ||
return this.values | ||
.map((v) => (v.includes(",") || v.includes(" ") ? `"${v}"` : v)) | ||
.join(", "); | ||
} | ||
|
||
/** | ||
* Get string values as a list | ||
* | ||
* @returns Values in {@link Field} as a list. | ||
*/ | ||
public get(): string[] { | ||
return this.values; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum FieldPosition { | ||
HEADER, | ||
TRAILER | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Field } from "./Field"; | ||
import { FieldPosition } from "./FieldPosition"; | ||
|
||
export type FieldsOptions = { fields?: Field[]; encoding?: string; }; | ||
|
||
/** | ||
* Collection of Field entries mapped by name. | ||
*/ | ||
export class Fields { | ||
private readonly entries: Record<string, Field> = {}; | ||
private readonly encoding: string; | ||
|
||
constructor({ fields = [], encoding = "utf-8" }: FieldsOptions) { | ||
fields.forEach(this.setField.bind(this)); | ||
this.encoding = encoding; | ||
} | ||
|
||
/** | ||
* Set entry for a {@link Field} name. The `name` | ||
* attribute will be used to key the collection. | ||
* | ||
* @param field The {@link Field} to set. | ||
*/ | ||
public setField(field: Field): void { | ||
this.entries[field.name] = field; | ||
} | ||
|
||
/** | ||
* Retrieve {@link Field} entry by name. | ||
* | ||
* @param name The name of the {@link Field} entry | ||
* to retrieve | ||
* @returns The {@link Field} if it exists. | ||
*/ | ||
public getField(name: string): Field | undefined { | ||
return this.entries[name]; | ||
} | ||
|
||
/** | ||
* Delete entry from collection. | ||
* | ||
* @param name Name of the entry to delete. | ||
*/ | ||
public removeField(name: string): void { | ||
delete this.entries[name]; | ||
} | ||
|
||
/** | ||
* Helper function for retrieving specific types of fields. | ||
* Used to grab all headers or all trailers. | ||
* | ||
* @param kind {@link FieldPosition} of entries to retrieve. | ||
* @returns The {@link Field} entries with the specified | ||
* {@link FieldPosition}. | ||
*/ | ||
public getByType(kind: FieldPosition): Field[] { | ||
return Object.values(this.entries).filter((field) => field.kind === kind); | ||
} | ||
} |