Skip to content

Commit

Permalink
Fix issue #157
Browse files Browse the repository at this point in the history
  • Loading branch information
Elbahkiry committed Sep 6, 2024
1 parent 7efccbc commit 6d40065
Showing 1 changed file with 123 additions and 121 deletions.
244 changes: 123 additions & 121 deletions ADDING-NEW-VENDOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
Assume that the name of the vendor is **abc** and the name of the service **xyz**, Let's start with the steps:

- ### [**Config.toml**](config.toml)

> **Note**: You will find an explaination for **config.toml** section in [**README.md**](README.md).
You should add a section with the name of the service in [**config.toml**](./config.toml).

You should add the required variables of the service. There are **two** types of variables in **config.toml** file:

- **Mandatory**:

> The **mandatory** variable is the variable which **ICAPeg server** uses for processing **ICAP** message.
- **Mandatory variables**:
- **vendor**
- **service_caption**
Expand All @@ -26,13 +26,13 @@ Assume that the name of the vendor is **abc** and the name of the service **xyz*
- **process_extensions**
- **reject_extensions**
- **bypass_extensions**

- **Optional**

> The **optional** variable is the variable which the service (eg: **xyz**) use for processing **HTTP** message, adding **optional** variables is up to the developer.
For example, if the name of the service is **xyz** and its vendor is **abc**, the section will be like the following section:

```toml
[xyz]
## mandatory variables
Expand All @@ -51,179 +51,181 @@ Assume that the name of the vendor is **abc** and the name of the service **xyz*
base_url = "http://abc/" #
scan_endpoint = "xyz.com"
api_key = "<api key>"
timeout = 300
timeout = 300 #seconds , ICAP will return 408 - Request timeou
fail_threshold = 2
max_filesize = 0
max_filesize = 0 #bytes
return_original_if_max_file_size_exceeded=false
return_400_if_file_ext_rejected=false
```

- ### **Vendor package** (abc package)

- Add a new package named **abc** in the [service](./service/services) directory.

- Add file named **config.go** in **abc** package and follow these instructions in this file.

- Create a struct named **Abc** with the required attributes of any service to this vendor.

- **Mandatory fields**:

- **xICAPMetadata**: It's the id of every **ICAP** request sent to **ICAPeg**.
- **httpMsg**: It's an instance from [**HttpMsg**](http-message/httpMessage.go) struct which groups two field (**HTTP request** and **HTTP response**). The developer can process the **HTTP message(request or response)** through this instance.
- **serviceName**: It's the service name value.
- **methodName**: It's method name value.

- **Optional fields**:

- **generalFunc**: It's an instance from [**GeneralFunc**](service/services-utilities/general-functions/general-functions.go) struct which has a lot of function that may help the developer in processing **HTTP messages**.

```go
type Abc struct {
//mandatory
xICAPMetadata string
httpMsg *utils.HttpMsg
serviceName string
methodName string
httpMsg *http_message.HttpMsg
serviceName string
methodName string
bypassExts []string
processExts []string
rejectExts []string
extArrs []services_utilities.Extension
processExts []string
rejectExts []string
extArrs []services_utilities.Extension

//optional, it's up to you and to optional variables have been added in the service section in config.toml file (you should map them with these struct fields)
generalFunc *general_functions.GeneralFunc //optional helper field
base_url = "echo"
scan_endpoint = "echo"
api_key = "<api key>"
timeout = 300 #seconds , ICAP will return 408 - Request timeout
fail_threshold = 2
max_filesize = 0 #bytes
return_original_if_max_file_size_exceeded=false
generalFunc *general_functions.GeneralFunc //optional helper field
BaseURL string
ScanEndpoint string
APIKey string
Timeout time.Duration
FailThreshold int
maxFileSize int
returnOrigIfMaxSizeExc bool
return400IfFileExtRejected bool
}
```

- Add **doOnce** and **abcConfig** variables:

- **doOnce**: It's a variable from [**sync**](https://pkg.go.dev/sync) package. It's used to apply the singular pattern to the service's struct, read the service's **config.toml** file section only one time once **ICAPeg** runs.
- **abcConfig**: It's an instance from **Abc** struct to store the service's **config.toml** file section variables and store them in memory through it.

```go
var doOnce sync.Once
var abcConfig *Abc
```

- Add **InitAbcConfig** function:

It's used to read service's **config.toml** file section **optional** variables and store them in memory using **abcConfig** instance.

```go
func InitEchoConfig(serviceName string) {
doOnce.Do(func() {
echoConfig = &Echo{
maxFileSize: readValues.ReadValuesInt(serviceName + ".max_filesize"),
bypassExts: readValues.ReadValuesSlice(serviceName + ".bypass_extensions"),
processExts: readValues.ReadValuesSlice(serviceName + ".process_extensions"),
rejectExts: readValues.ReadValuesSlice(serviceName + ".reject_extensions"),
BaseURL: readValues.ReadValuesString(serviceName + ".base_url"),
Timeout: readValues.ReadValuesDuration(serviceName+".timeout") * time.Second,
APIKey: readValues.ReadValuesString(serviceName + ".api_key"),
ScanEndpoint: readValues.ReadValuesString(serviceName + ".scan_endpoint"),
FailThreshold: readValues.ReadValuesInt(serviceName + ".fail_threshold"),
returnOrigIfMaxSizeExc: readValues.ReadValuesBool(serviceName + ".return_original_if_max_file_size_exceeded"),
return400IfFileExtRejected: readValues.ReadValuesBool(serviceName + ".return_400_if_file_ext_rejected"),
}
echoConfig.extArrs = services_utilities.InitExtsArr(echoConfig.processExts, echoConfig.rejectExts, echoConfig.bypassExts)
})
func InitAbcConfig(serviceName string) {
doOnce.Do(func() {
abcConfig = &Abc{
maxFileSize: readValues.ReadValuesInt(serviceName + ".max_filesize"),
bypassExts: readValues.ReadValuesSlice(serviceName + ".bypass_extensions"),
processExts: readValues.ReadValuesSlice(serviceName + ".process_extensions"),
rejectExts: readValues.ReadValuesSlice(serviceName + ".reject_extensions"),
BaseURL: readValues.ReadValuesString(serviceName + ".base_url"),
Timeout: readValues.ReadValuesDuration(serviceName+".timeout") * time.Second,
APIKey: readValues.ReadValuesString(serviceName + ".api_key"),
ScanEndpoint: readValues.ReadValuesString(serviceName + ".scan_endpoint"),
FailThreshold: readValues.ReadValuesInt(serviceName + ".fail_threshold"),
returnOrigIfMaxSizeExc: readValues.ReadValuesBool(serviceName + ".return_original_if_max_file_size_exceeded"),
return400IfFileExtRejected: readValues.ReadValuesBool(serviceName + ".return_400_if_file_ext_rejected"),
}
abcConfig.extArrs = services_utilities.InitExtsArr(abcConfig.processExts, abcConfig.rejectExts, abcConfig.bypassExts)
})
}
```




- Add a function named **NewAbcService** which creates a service from abc vendor.

It extracts service configuration from **abcConfig** variable.

```go
func NewAbcService(serviceName, methodName string, httpMsg *utils.HttpMsg, xICAPMetadata string) *abc {
return &Abc{
//mandatory
xICAPMetadata: xICAPMetadata, //the id of the ICAP request
httpMsg: httpMsg,
serviceName: serviceName,
methodName: methodName,
bypassExts: echoConfig.bypassExts,
processExts: echoConfig.processExts,
rejectExts: echoConfig.rejectExts,
//optional
generalFunc: general_functions.NewGeneralFunc(httpMsg), //optional helper
maxFileSize: abcConfig.maxFileSize,
extArrs: echoConfig.extArrs,
BaseURL: abcConfig.BaseURL,
Timeout: abcConfig.Timeout * time.Second,
APIKey: abcConfig.APIKey,
ScanEndpoint: abcConfig.ScanEndpoint,
FailThreshold: abcConfig.FailThreshold,
returnOrigIfMaxSizeExc: abcConfig.returnOrigIfMaxSizeExc,
}
func NewAbcService(serviceName, methodName string, httpMsg *http_message.HttpMsg, xICAPMetadata string) *Abc{
return &Abc{
//mandatory
xICAPMetadata: xICAPMetadata, //the id of the ICAP request
httpMsg: httpMsg,
serviceName: serviceName,
methodName: methodName,
bypassExts: abcConfig.bypassExts,
processExts: abcConfig.processExts,
rejectExts: abcConfig.rejectExts,
//optional
generalFunc: general_functions.NewGeneralFunc(httpMsg, xICAPMetadata), //optional helper
maxFileSize: abcConfig.maxFileSize,
extArrs: abcConfig.extArrs,
BaseURL: abcConfig.BaseURL,
Timeout: abcConfig.Timeout * time.Second,
APIKey: abcConfig.APIKey,
ScanEndpoint: abcConfig.ScanEndpoint,
FailThreshold: abcConfig.FailThreshold,
returnOrigIfMaxSizeExc: abcConfig.returnOrigIfMaxSizeExc,
}
}
```

- Create **abc.go** in **abc** package and follow these instructions in this file.

- Add function **Processing** to **abc** struct to implement the interface

```go
//Processing is a func used for to processing the http message
func (reciever *Abc) Processing(partial bool) (int, interface{}, map[string]string, map[string]interface{}, map[string]interface{}, map[string]interface{}) {
// your implementation
}
```
- Create **abc.go** in **abc** package and follow these instructions in this file.

- Add function **Processing** to **abc** struct to implement the interface

The values **Processing() function** paramaters:
```go
//Processing is a func used for to processing the http message
func (reciever *Abc) Processing(partial bool) (int, interface{}, map[string]string, map[string]interface{}, map[string]interface{}, map[string]interface{}) {
// your implementation
}
```

- **partial bool**: Boolean variable refer to wether the content is partial content or complete content.

The values **Processing() function** returns:

- **int**: ICAP response status code.
- **interface{}**: HTTP message after processing, It can be HTTP request if the ICAP request methos is REQMOD or HTTP response if the ICAP request methos is RESPMOD.
- **map[string]string**: map contains any headers related to the vendor and wanted to be added to ICAP response.
- **map[string]interface{}**: map contains HTTP message headers before the service of the vendor start processing the message.
- **map[string]interface{}**: map contains HTTP message headers after the service of the vendor started processing the message.
- **map[string]interface{}**: map contains any information the service of the vendor wants to log.
The values **Processing() function** paramaters:

- **partial bool**: Boolean variable refer to wether the content is partial content or complete content.

The values **Processing() function** returns:

- **int**: ICAP response status code.
- **interface{}**: HTTP message after processing, It can be HTTP request if the ICAP request methos is REQMOD or HTTP response if the ICAP request methos is RESPMOD.
- **map[string]string**: map contains any headers related to the vendor and wanted to be added to ICAP response.
- **map[string]interface{}**: map contains HTTP message headers before the service of the vendor start processing the message.
- **map[string]interface{}**: map contains HTTP message headers after the service of the vendor started processing the message.
- **map[string]interface{}**: map contains any information the service of the vendor wants to log.

- ### [**service.go**](service/service.go)

- Add the name of the new vendor as a constant variable in [service.go](service/service.go) at the start of the file in the constants section.

```go
//Vendors names
const (
VendorEcho = "echo"
VendorAbc = "abc"
VendorEcho = "echo"
VendorAbc = "abc"
)
```

- Add a case in the switch case in **GetService** function by the new vendor

```go
func GetService(vendor, serviceName, methodName string, httpMsg *utils.HttpMsg, xICAPMetadata string) Service {
switch vendor {
case VendorEcho:
return echo.NewEchoService(serviceName, methodName, httpMsg, xICAPMetadata)
case VendorABC:
return abc.NewAbcService(serviceName, methodName, httpMsg, xICAPMetadata)
}
return nil
switch vendor {
case VendorEcho:
return echo.NewEchoService(serviceName, methodName, httpMsg, xICAPMetadata)
case VendorAbc:
return abc.NewAbcService(serviceName, methodName, httpMsg, xICAPMetadata)
}
return nil
}
```

- Add a case in the switch case in **InitServiceConfig** function by the new vendor

```go
func InitServiceConfig(vendor, serviceName string) {
switch vendor {
case VendorEcho:
echo.InitEchoConfig(serviceName)
case VendorAbc:
echo.InitAbcConfig(serviceName)
}
switch vendor {
case VendorEcho:
echo.InitEchoConfig(serviceName)
case VendorAbc:
abc.InitAbcConfig(serviceName)
}
}
```

Expand Down

0 comments on commit 6d40065

Please sign in to comment.