2020-10-14 18:06:28 +02:00
import requests
import json
import logging
2022-07-28 18:00:36 +02:00
from requests . structures import CaseInsensitiveDict
2020-10-14 18:06:28 +02:00
from pyexecplugins . pyexecplugins import PyExecPlugin
class Plugin ( PyExecPlugin ) :
name = " Http "
2023-03-14 13:20:39 +01:00
2020-10-14 18:06:28 +02:00
taskdef = {
" name " : " pyrest " ,
" description " : " Execute an HTTP request with pyrest worker " ,
" inputKeys " : [ " url " , " body " , " contentType " , " method " , " accept " , " headers " , " connectionTimeout " , " readTimeout " ] ,
" outputKeys " : [ " body " , " status " , " reason " , " headers " ] ,
" ownerEmail " : " m.lettere@gmail.com "
}
2023-03-14 13:20:39 +01:00
2021-03-22 16:36:35 +01:00
def __init__ ( self , data , config = None ) :
super ( ) . __init__ ( data , config )
2020-10-14 18:06:28 +02:00
self . method = data . get ( " method " ) or " get "
self . url = data . get ( " url " )
self . headers = data . get ( " headers " ) or { }
2022-07-28 18:00:36 +02:00
self . headers = CaseInsensitiveDict ( self . headers )
2020-10-14 18:06:28 +02:00
self . contenttype = self . headers . get ( " Content-Type " )
self . accept = self . headers . get ( " Accept " )
self . body = data . get ( " body " )
self . params = data . get ( " params " )
self . expect = data . get ( " expect " )
self . fail = data . get ( " fail " )
2023-03-14 13:20:39 +01:00
self . conntimeout = data . get ( " connection-timeout " ) or 5
self . readtimeout = data . get ( " read-timeout " ) or 10
self . notimeout = ( data . get ( " no-timeout " ) in ( True , " true " , " True " , " TRUE " , 1 , " 1 " , " y " , " Y " , " yes " , " YES " ) ) or False
2023-07-17 17:31:13 +02:00
def adaptMultipart ( self , parts ) :
req = { }
for p in parts :
part = parts [ p ]
if ( type ( part ) == str ) :
req [ p ] = part
elif ( type ( part ) == list and len ( part ) > 0 and len ( part ) < = 2 ) :
if len ( part ) == 1 :
req [ p ] = ( p , part [ 0 ] )
elif len ( part ) == 2 and part [ 1 ] . find ( " json " ) :
req [ p ] = ( p , json . dumps ( part [ 0 ] ) , part [ 1 ] )
else :
req [ p ] = ( p , part [ 0 ] , part [ 1 ] )
else :
raise Exception ( " Unable to parse multipart request. For every key either single string or an array matching requests tuple format is expected. Got %s with length %d for key %s " % ( type ( part ) , len ( part ) , p ) )
return req
2020-10-14 18:06:28 +02:00
def doRequest ( self ) :
2023-07-18 16:19:15 +02:00
logging . getLogger ( " pyexec " ) . debug ( " %s - %s - %s - %s " , self . method , self . url , self . contenttype , self . accept )
2020-10-14 18:06:28 +02:00
if self . contenttype != None and self . contenttype . find ( " json " ) != - 1 :
2020-11-12 18:38:54 +01:00
self . request = requests . Request ( self . method , self . url , headers = self . headers , json = self . body )
2023-07-18 16:19:15 +02:00
elif self . contenttype != None and self . contenttype . find ( " multipart/form-data " ) != - 1 :
2023-07-17 17:31:13 +02:00
self . headers . pop ( " content-type " )
self . request = requests . Request ( self . method , self . url , headers = self . headers , files = self . adaptMultipart ( self . body ) )
2022-09-07 16:49:06 +02:00
elif self . contenttype != None and self . contenttype . find ( " text " ) != - 1 :
self . request = requests . Request ( self . method , self . url , headers = self . headers , data = self . body . encode ( ' utf-8 ' ) )
2020-10-14 18:06:28 +02:00
else :
2020-11-12 18:38:54 +01:00
self . request = requests . Request ( self . method , self . url , headers = self . headers , data = self . body , params = self . params )
2023-03-14 13:20:39 +01:00
2020-11-12 18:38:54 +01:00
self . request = self . request . prepare ( )
2023-03-14 13:20:39 +01:00
if self . notimeout :
timeout = None
else :
timeout = ( self . conntimeout , self . readtimeout )
2023-04-17 17:33:22 +02:00
logging . getLogger ( " pyexec " ) . info ( " %s url= %s body= %s conntimeout= %d readtimeout= %d " , self . method , self . request . url , self . body , self . conntimeout , self . readtimeout )
2023-03-14 13:20:39 +01:00
self . response = requests . Session ( ) . send ( self . request , timeout = timeout )
2020-10-14 18:06:28 +02:00
return self . response
def computeStatus ( self ) :
if self . fail == False :
return " COMPLETED "
elif self . expect == None :
return " COMPLETED " if self . response . ok else " FAILED "
else :
if type ( self . expect ) == list :
return " COMPLETED " if ( self . response . status_code in self . expect ) else " FAILED "
else :
return " COMPLETED " if ( self . response . status_code == self . expect ) else " FAILED "
2023-03-14 13:20:39 +01:00
2020-10-14 18:06:28 +02:00
def buildOutput ( self , status ) :
hdrs = { }
for k in self . response . headers . keys ( ) : hdrs [ k ] = self . response . headers [ k ]
2020-11-12 18:38:54 +01:00
logging . getLogger ( " pyexec " ) . info ( " Response: {} {} " . format ( self . response . status_code , self . response . reason ) )
2020-10-14 18:06:28 +02:00
if hdrs . get ( " Content-Type " ) != None and hdrs [ " Content-Type " ] . find ( " json " ) != - 1 or self . accept != None and self . accept . find ( " json " ) != - 1 :
outbody = self . response . json ( ) if len ( self . response . content ) != 0 else None
else :
outbody = self . response . text
2023-03-14 13:20:39 +01:00
2020-11-12 18:38:54 +01:00
logging . getLogger ( " pyexec " ) . debug ( " %s " , outbody )
2020-10-14 18:06:28 +02:00
if status == " FAILED " :
2020-11-12 18:38:54 +01:00
raise Exception ( " HTTP call failed with status {} ( {} ) - {} " . format ( self . response . status_code , self . response . reason , str ( outbody ) ) )
2020-10-14 18:06:28 +02:00
return {
" body " : outbody ,
" headers " : hdrs ,
" status " : self . response . status_code ,
" reason " : self . response . reason
}
2023-03-14 13:20:39 +01:00
2020-10-14 18:06:28 +02:00
def execute ( self ) :
self . doRequest ( )
status = self . computeStatus ( )
return self . buildOutput ( status )