Skip to content

Latest commit

 

History

History
232 lines (184 loc) · 9.65 KB

ADDING-NEW-VENDOR.md

File metadata and controls

232 lines (184 loc) · 9.65 KB

How to add a new service for a new vendor?

Assume that the name of the vendor is abc and the name of the service xyz, Let's start with the steps:

  • Note: You will find an explaination for config.toml section in README.md.

    You should add a section with the name of the service in 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
        • service_tag
        • req_mode
        • resp_mode
        • shadow_service
        • preview_bytes
        • preview_enabled
        • 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:

    [xyz]
    ## mandatory variables
    vendor = "abc"
    service_caption= "XYZ service"   
    service_tag = "ABC ICAP"  
    req_mode=true 
    resp_mode=true 
    shadow_service=false
    preview_bytes = "1024" 
    preview_enabled = true
    process_extensions = ["pdf", "zip", "com"] 
    reject_extensions = ["docx"]
    bypass_extensions = ["*"]
    ## optional variables
    base_url = "http://abc/" #
    scan_endpoint = "xyz.com"
    api_key = "<api key>"
    timeout  = 300 
    fail_threshold = 2
    max_filesize = 0 
  • Vendor package (abc package)

    • Add a new package named abc in the service 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 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 struct which has a lot of function that may help the developer in processing HTTP messages.
        type Abc struct {
            //mandatory
            xICAPMetadata              string
        	httpMsg                *utils.HttpMsg
        	serviceName            string
        	methodName             string
            bypassExts                 []string
        	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
        }
      • Add doOnce and abcConfig variables:

        • doOnce: It's a variable from 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.
        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.

        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)
        	})
        }
      • Add a function named NewAbcService which creates a service from abc vendor.

        It extracts service configuration from abcConfig variable.

        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,
        	}
        }
    • Create abc.go in abc package and follow these instructions in this file.

      • Add function Processing to abc struct to implement the interface

        //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
        }

        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.
    • Add the name of the new vendor as a constant variable in service.go at the start of the file in the constants section.
//Vendors names
const (
	VendorEcho      = "echo"
	VendorAbc   	= "abc"
)
  • Add a case in the switch case in GetService function by the new vendor

    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
    }
  • Add a case in the switch case in InitServiceConfig function by the new vendor

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

Please, check echo vendor to relate to above explanation.

Now you can run ICAPeg and try it with your service.