Message ID | 20200914145712.4989-14-christian.storm@siemens.com |
---|---|
State | Accepted |
Headers | show |
Series | [01/14] channel_curl: Make setting request_body symmetric | expand |
Hi Christian, On 14.09.20 16:57, Christian Storm wrote: > Signed-off-by: Christian Storm <christian.storm@siemens.com> > --- > corelib/channel_curl.c | 28 +++++++++++++++++++--------- > include/channel_curl.h | 1 + > 2 files changed, 20 insertions(+), 9 deletions(-) > Is a new backend planned ? Hawkbit does not have in its DDI interface a PATCH method. Just curious... > diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c > index 5142c71..6521850 100644 > --- a/corelib/channel_curl.c > +++ b/corelib/channel_curl.c > @@ -767,7 +767,7 @@ static channel_op_res_t parse_reply(channel_data_t *channel_data, output_data_t > return CHANNEL_OK; > } > > -static channel_op_res_t channel_post_method(channel_t *this, void *data) > +static channel_op_res_t channel_post_method(channel_t *this, void *data, int method) > { > channel_curl_t *channel_curl = this->priv; > assert(data != NULL); > @@ -793,20 +793,29 @@ static channel_op_res_t channel_post_method(channel_t *this, void *data) > goto cleanup_header; > } > > - if ((curl_easy_setopt(channel_curl->handle, CURLOPT_POST, 1L) != CURLE_OK) || > - (curl_easy_setopt(channel_curl->handle, CURLOPT_POSTFIELDS, > - channel_data->request_body) != CURLE_OK)) { > + CURLcode curl_result; > + if (method == CHANNEL_PATCH) { > + curl_result = curl_easy_setopt(channel_curl->handle, CURLOPT_CUSTOMREQUEST, "PATCH"); > + } else { > + curl_result = curl_easy_setopt(channel_curl->handle, CURLOPT_POST, 1L); > + } > + if (curl_result != CURLE_OK) { > + result = CHANNEL_EINIT; > + ERROR("Set POST/PATCH channel method option failed."); > + goto cleanup_header; > + } > + if (curl_easy_setopt(channel_curl->handle, CURLOPT_POSTFIELDS, channel_data->request_body) != CURLE_OK) { > result = CHANNEL_EINIT; > - ERROR("Set POST channel method option failed."); > + ERROR("Set POST/PATCH channel data option failed."); > goto cleanup_header; > } > if (channel_data->debug) { > - TRACE("Posted to %s: %s", channel_data->url, channel_data->request_body); > + TRACE("POSTed/PATCHed to %s: %s", channel_data->url, channel_data->request_body); > } > > CURLcode curlrc = curl_easy_perform(channel_curl->handle); > if (curlrc != CURLE_OK) { > - ERROR("Channel put operation failed (%d): '%s'", curlrc, > + ERROR("Channel POST/PATCH operation failed (%d): '%s'", curlrc, > curl_easy_strerror(curlrc)); > result = channel_map_curl_error(curlrc); > goto cleanup_header; > @@ -908,9 +917,10 @@ channel_op_res_t channel_put(channel_t *this, void *data) > case CHANNEL_PUT: > return channel_put_method(this, data); > case CHANNEL_POST: > - return channel_post_method(this, data); > + case CHANNEL_PATCH: > + return channel_post_method(this, data, channel_data->method); > default: > - TRACE("Channel method (POST, PUT) is not set !"); > + TRACE("Channel method (POST, PUT, PATCH) is not set !"); > return CHANNEL_EINIT; > } > } > diff --git a/include/channel_curl.h b/include/channel_curl.h > index 6b4f4da..c3418a5 100644 > --- a/include/channel_curl.h > +++ b/include/channel_curl.h > @@ -25,6 +25,7 @@ typedef enum { > CHANNEL_GET, > CHANNEL_POST, > CHANNEL_PUT, > + CHANNEL_PATCH, > } channel_method_t; > > typedef enum { > Best regards, Stefano
Hi Stefano, > > Signed-off-by: Christian Storm <christian.storm@siemens.com> > > --- > > corelib/channel_curl.c | 28 +++++++++++++++++++--------- > > include/channel_curl.h | 1 + > > 2 files changed, 20 insertions(+), 9 deletions(-) > > > > Is a new backend planned ? Hawkbit does not have in its DDI interface a > PATCH method. Just curious... Yes, indeed, too obvious, isn't it? :) I'm currently implementing support for a new version of the Siemens MindSphere Firmware Deployment Service [1] and this has deprecated POST in favor of PATCH ― for some REST endpoints at least. Mender.io also uses PATCH, e.g., for the /device/attributes REST endpoint [2]. So, for eventually supporting both (and probably some proprietary backends as well), I guess we need PATCH support. However, my broader plan is to actually not write new suricatta modules for particular backends but instead write a generic Lua suricatta module in C that allows one to write the "business logic" for particular backends in Lua. This generic suricatta Lua module provides the infrastructure / binding to SWUpdate (core) to the Lua realm. With "business logic" I mean the specific backend server handling like REST API banging and state communication, i.e., all that is specific to a particular backend. In essence it's the same story as we have with the ability to write handlers in Lua ― just for suricatta. The reason for this idea is a separation of means and control: In the C suricatta module world, both are intertwined and convoluted. Having the control logics in Lua and the means (in terms of the instrumentation of SWUpdate core) nicely wrapped up for the Lua realm to make use of separates those two, easing maintenance and hopefully lowering the bar to integrate more backends faster into SWUpdate. To get a bit more technical, the generic Lua suricatta module to be written in C exposes a register() function to the Lua realm so that the suricatta interface methods (include/suricatta/server.h) can be implemented in Lua, alongside a few other wrappers in order to call SWUpdate (core) functionality from within the Lua realm to, e.g., handle persistent state and doing communication. Again, the same story as with the Lua handlers. Currently, the `swupdate_suricatta.lua` Lua module looks like this: ```lua local suricatta = { sleep = function(seconds) end, install = function(ichannel, pchannel) end, download = function(ichannel, pchannel, path) end, get_tmpdir = function() end, } suricatta.status = { OK = 0, EERR = 1, EBADMSG = 2, EINIT = 3, EACCES = 4, EAGAIN = 5, UPDATE_AVAILABLE = 6, NO_UPDATE_AVAILABLE = 7, UPDATE_CANCELED = 8, ID_REQUESTED = 9, } suricatta.notify = { error = function(message) end, trace = function(message) end, debug = function(message) end, info = function(message) end, warn = function(message) end, progress = function(message) end, } suricatta.pstate = { get = function() end, save = function(state) end, reset = function() end, OK = '0', INSTALLED = '1', TESTING = '2', FAILED = '3', NOT_AVAILABLE = '4', ERROR = '5', WAIT = '6', IN_PROGRESS = '7', } suricatta.server = { register = function(name, functiont) end, HAS_PENDING_ACTION = 0, INSTALL_UPDATE = 1, SEND_TARGET_DATA = 2, GET_POLLING_INTERVAL = 3, SERVER_START = 4, SERVER_STOP = 5, IPC = 6, PRINT_HELP = 7, } suricatta.channel = { open = function(optiont) return { get = function(options) end, install = function(options) end, downloadonly = function(options, path) end, put = function(options) end, close = function() end, } end, content = { NONE = 0, JSON = 1, RAW = 2, }, method = { GET = 0, POST = 1, PUT = 2, PATCH = 3, } } return suricatta ``` Kind regards, Christian [1] https://developer.mindsphere.io/apis/edge-firmwaredeployment/api-firmwaredeployment-basics.html [2] https://docs.mender.io/api/#device-api-device-inventory
Hi Christian, On 15.09.20 11:36, Christian Storm wrote: > Hi Stefano, > >>> Signed-off-by: Christian Storm <christian.storm@siemens.com> >>> --- >>> corelib/channel_curl.c | 28 +++++++++++++++++++--------- >>> include/channel_curl.h | 1 + >>> 2 files changed, 20 insertions(+), 9 deletions(-) >>> >> >> Is a new backend planned ? Hawkbit does not have in its DDI interface a >> PATCH method. Just curious... > > Yes, indeed, too obvious, isn't it? :) > ;-) > I'm currently implementing support for a new version of the Siemens > MindSphere Firmware Deployment Service [1] and this has deprecated > POST in favor of PATCH ― for some REST endpoints at least. > > Mender.io also uses PATCH, e.g., for the /device/attributes REST > endpoint [2]. > > So, for eventually supporting both (and probably some proprietary > backends as well), I guess we need PATCH support. > Ok, got it. > > However, my broader plan is to actually not write new suricatta modules > for particular backends but instead write a generic Lua suricatta module > in C that allows one to write the "business logic" for particular > backends in Lua. This generic suricatta Lua module provides the > infrastructure / binding to SWUpdate (core) to the Lua realm. > With "business logic" I mean the specific backend server handling like > REST API banging and state communication, i.e., all that is specific to > a particular backend. > In essence it's the same story as we have with the ability to write > handlers in Lua ― just for suricatta. Yes, it is similar. > > The reason for this idea is a separation of means and control: In the > C suricatta module world, both are intertwined and convoluted. Having > the control logics in Lua and the means (in terms of the instrumentation > of SWUpdate core) nicely wrapped up for the Lua realm to make use of > separates those two, easing maintenance and hopefully lowering the bar > to integrate more backends faster into SWUpdate. I do not know if this could be generally better - for example, the REST-API in Mender requires a different approach for authentication (quite as JSON Token), and I guess that we need several external Lua libraries, while on C could ve more straightforward. So I guess each backend should be evaluated and estimated which is the best way to implement it. > > > To get a bit more technical, the generic Lua suricatta module to be > written in C exposes a register() function to the Lua realm so that the > suricatta interface methods (include/suricatta/server.h) can be > implemented in Lua, Ok - so the polling server (suricatta.c) can call the specific backend implementation, that is in Lua if so specified. I just like to have the same features we have now, for example streaming should still work with the Lua backend. > alongside a few other wrappers in order to call > SWUpdate (core) functionality from within the Lua realm to, e.g., handle > persistent state and doing communication. Again, the same story as with > the Lua handlers. > Currently, the `swupdate_suricatta.lua` Lua module looks like this: > ```lua > local suricatta = { > sleep = function(seconds) end, > install = function(ichannel, pchannel) end, > download = function(ichannel, pchannel, path) end, > get_tmpdir = function() end, > } > > suricatta.status = { > OK = 0, > EERR = 1, > EBADMSG = 2, > EINIT = 3, > EACCES = 4, > EAGAIN = 5, > UPDATE_AVAILABLE = 6, > NO_UPDATE_AVAILABLE = 7, > UPDATE_CANCELED = 8, > ID_REQUESTED = 9, > } > > suricatta.notify = { > error = function(message) end, > trace = function(message) end, > debug = function(message) end, > info = function(message) end, > warn = function(message) end, > progress = function(message) end, > } > > suricatta.pstate = { > get = function() end, > save = function(state) end, > reset = function() end, > OK = '0', > INSTALLED = '1', > TESTING = '2', > FAILED = '3', > NOT_AVAILABLE = '4', > ERROR = '5', > WAIT = '6', > IN_PROGRESS = '7', > } > > suricatta.server = { > register = function(name, functiont) end, > HAS_PENDING_ACTION = 0, > INSTALL_UPDATE = 1, > SEND_TARGET_DATA = 2, > GET_POLLING_INTERVAL = 3, > SERVER_START = 4, > SERVER_STOP = 5, > IPC = 6, > PRINT_HELP = 7, > } > > suricatta.channel = { > open = function(optiont) > return { > get = function(options) end, > install = function(options) end, > downloadonly = function(options, path) end, > put = function(options) end, > close = function() end, > } > end, > content = { > NONE = 0, > JSON = 1, > RAW = 2, > }, > method = { > GET = 0, > POST = 1, > PUT = 2, > PATCH = 3, > } > } > > return suricatta > ``` > > > Kind regards, > Christian Best regards, Stefano
Hi Stefano, > > > > Signed-off-by: Christian Storm <christian.storm@siemens.com> > > > > --- > > > > corelib/channel_curl.c | 28 +++++++++++++++++++--------- > > > > include/channel_curl.h | 1 + > > > > 2 files changed, 20 insertions(+), 9 deletions(-) > > > > > > > > > > Is a new backend planned ? Hawkbit does not have in its DDI interface a > > > PATCH method. Just curious... > > > > Yes, indeed, too obvious, isn't it? :) > > > > ;-) > > > I'm currently implementing support for a new version of the Siemens > > MindSphere Firmware Deployment Service [1] and this has deprecated > > POST in favor of PATCH ― for some REST endpoints at least. > > > > Mender.io also uses PATCH, e.g., for the /device/attributes REST > > endpoint [2]. > > > > So, for eventually supporting both (and probably some proprietary > > backends as well), I guess we need PATCH support. > > > > Ok, got it. > > > > > However, my broader plan is to actually not write new suricatta modules > > for particular backends but instead write a generic Lua suricatta module > > in C that allows one to write the "business logic" for particular > > backends in Lua. This generic suricatta Lua module provides the > > infrastructure / binding to SWUpdate (core) to the Lua realm. > > With "business logic" I mean the specific backend server handling like > > REST API banging and state communication, i.e., all that is specific to > > a particular backend. > > In essence it's the same story as we have with the ability to write > > handlers in Lua ― just for suricatta. > > Yes, it is similar. > > > > > The reason for this idea is a separation of means and control: In the > > C suricatta module world, both are intertwined and convoluted. Having > > the control logics in Lua and the means (in terms of the instrumentation > > of SWUpdate core) nicely wrapped up for the Lua realm to make use of > > separates those two, easing maintenance and hopefully lowering the bar > > to integrate more backends faster into SWUpdate. > > I do not know if this could be generally better - for example, the REST-API in > Mender requires a different approach for authentication (quite as JSON Token), > and I guess that we need several external Lua libraries, while on C could ve > more straightforward. So I guess each backend should be evaluated and > estimated which is the best way to implement it. It's not about better or worse, it's about having options :) I don't quite like the idea to pull in (external) Lua libraries for this, to be honest. If there is a need for functionality not available in the Lua realm to suricatta modules written in Lua, the same need would be there if we code the suricatta module in C instead. Then, we could as well code this missing functionality in C and (additionally) make it available to the Lua realm. Then, both options (write it in C and write it in Lua) can profit. The added overhead of also writing a wrapper to the Lua realm is small to negligible, I think, since all the infrastructure for doing so is already in SWUpdate. Hence, I don't like the two options (write it in C or in Lua) to have different feature sets in terms of what functionality they support and can make use of from SWUpdate (core). Instead, I'd like to have it like we have it now for the handlers: Both are on par and it's not a technical (feature) choice of one over the other. That said, I do indeed think that the separation of means and control can be beneficial to, e.g., maintenance, development speed, and testability. After all, this is the reason for the idea as I've seen too many projects where this would definitely have helped. So, it's not about deprecating the option to write suricatta modules in C nor about having an inferior option to write those in Lua ― which makes no sense as nobody would use this option because of its inferiority. It's actually ― as you said ― about then having a choice of whether a backend support suricatta module is better implemented in Lua or C, with their respective pros and cons. > > To get a bit more technical, the generic Lua suricatta module to be > > written in C exposes a register() function to the Lua realm so that the > > suricatta interface methods (include/suricatta/server.h) can be > > implemented in Lua, > > Ok - so the polling server (suricatta.c) can call the specific backend > implementation, that is in Lua if so specified. Yes, exactly. > I just like to have the same features we have now, for example streaming > should still work with the Lua backend. Absolutely. Both should be on a par. > > alongside a few other wrappers in order to call > > SWUpdate (core) functionality from within the Lua realm to, e.g., handle > > persistent state and doing communication. Again, the same story as with > > the Lua handlers. > > Currently, the `swupdate_suricatta.lua` Lua module looks like this: > > ```lua > > local suricatta = { > > sleep = function(seconds) end, > > install = function(ichannel, pchannel) end, > > download = function(ichannel, pchannel, path) end, > > get_tmpdir = function() end, > > } > > > > suricatta.status = { > > OK = 0, > > EERR = 1, > > EBADMSG = 2, > > EINIT = 3, > > EACCES = 4, > > EAGAIN = 5, > > UPDATE_AVAILABLE = 6, > > NO_UPDATE_AVAILABLE = 7, > > UPDATE_CANCELED = 8, > > ID_REQUESTED = 9, > > } > > > > suricatta.notify = { > > error = function(message) end, > > trace = function(message) end, > > debug = function(message) end, > > info = function(message) end, > > warn = function(message) end, > > progress = function(message) end, > > } > > > > suricatta.pstate = { > > get = function() end, > > save = function(state) end, > > reset = function() end, > > OK = '0', > > INSTALLED = '1', > > TESTING = '2', > > FAILED = '3', > > NOT_AVAILABLE = '4', > > ERROR = '5', > > WAIT = '6', > > IN_PROGRESS = '7', > > } > > > > suricatta.server = { > > register = function(name, functiont) end, > > HAS_PENDING_ACTION = 0, > > INSTALL_UPDATE = 1, > > SEND_TARGET_DATA = 2, > > GET_POLLING_INTERVAL = 3, > > SERVER_START = 4, > > SERVER_STOP = 5, > > IPC = 6, > > PRINT_HELP = 7, > > } > > > > suricatta.channel = { > > open = function(optiont) > > return { > > get = function(options) end, > > install = function(options) end, > > downloadonly = function(options, path) end, > > put = function(options) end, > > close = function() end, > > } > > end, > > content = { > > NONE = 0, > > JSON = 1, > > RAW = 2, > > }, > > method = { > > GET = 0, > > POST = 1, > > PUT = 2, > > PATCH = 3, > > } > > } > > > > return suricatta > > ``` Besten Gruß, Christian
Hi Christian, On 16.09.20 10:16, Christian Storm wrote: > Hi Stefano, > > >>>>> Signed-off-by: Christian Storm <christian.storm@siemens.com> >>>>> --- >>>>> corelib/channel_curl.c | 28 +++++++++++++++++++--------- >>>>> include/channel_curl.h | 1 + >>>>> 2 files changed, 20 insertions(+), 9 deletions(-) >>>>> >>>> >>>> Is a new backend planned ? Hawkbit does not have in its DDI interface a >>>> PATCH method. Just curious... >>> >>> Yes, indeed, too obvious, isn't it? :) >>> >> >> ;-) >> >>> I'm currently implementing support for a new version of the Siemens >>> MindSphere Firmware Deployment Service [1] and this has deprecated >>> POST in favor of PATCH ― for some REST endpoints at least. >>> >>> Mender.io also uses PATCH, e.g., for the /device/attributes REST >>> endpoint [2]. >>> >>> So, for eventually supporting both (and probably some proprietary >>> backends as well), I guess we need PATCH support. >>> >> >> Ok, got it. >> >>> >>> However, my broader plan is to actually not write new suricatta modules >>> for particular backends but instead write a generic Lua suricatta module >>> in C that allows one to write the "business logic" for particular >>> backends in Lua. This generic suricatta Lua module provides the >>> infrastructure / binding to SWUpdate (core) to the Lua realm. >>> With "business logic" I mean the specific backend server handling like >>> REST API banging and state communication, i.e., all that is specific to >>> a particular backend. >>> In essence it's the same story as we have with the ability to write >>> handlers in Lua ― just for suricatta. >> >> Yes, it is similar. >> >>> >>> The reason for this idea is a separation of means and control: In the >>> C suricatta module world, both are intertwined and convoluted. Having >>> the control logics in Lua and the means (in terms of the instrumentation >>> of SWUpdate core) nicely wrapped up for the Lua realm to make use of >>> separates those two, easing maintenance and hopefully lowering the bar >>> to integrate more backends faster into SWUpdate. >> >> I do not know if this could be generally better - for example, the REST-API in >> Mender requires a different approach for authentication (quite as JSON Token), >> and I guess that we need several external Lua libraries, while on C could ve >> more straightforward. So I guess each backend should be evaluated and >> estimated which is the best way to implement it. > > It's not about better or worse, it's about having options :) > Exactly - IMHO there will be cases where it is better to code in C, and other cases where Lua is more suitable. As we have now for handlers. > I don't quite like the idea to pull in (external) Lua libraries for > this, to be honest. Me too. This increases dependencies and I would like to avoid this. > If there is a need for functionality not available > in the Lua realm to suricatta modules written in Lua, the same need > would be there if we code the suricatta module in C instead. Then, we > could as well code this missing functionality in C and (additionally) > make it available to the Lua realm. Then, both options (write it in > C and write it in Lua) can profit. The added overhead of also writing > a wrapper to the Lua realm is small to negligible, I think, since all > the infrastructure for doing so is already in SWUpdate. Fully agree. > > Hence, I don't like the two options (write it in C or in Lua) to have > different feature sets in terms of what functionality they support and > can make use of from SWUpdate (core). Exactly - goal is that we can have an option, but chossing one of them does not mean to have limitations. > Instead, I'd like to have it like we have it now for the handlers: Both > are on par and it's not a technical (feature) choice of one over the > other. Right. > > That said, I do indeed think that the separation of means and control > can be beneficial to, e.g., maintenance, development speed, and > testability. After all, this is the reason for the idea as I've seen too > many projects where this would definitely have helped. Fully agree. > > So, it's not about deprecating the option to write suricatta modules in > C nor about having an inferior option to write those in Lua ― which > makes no sense as nobody would use this option because of its inferiority. > It's actually ― as you said ― about then having a choice of whether > a backend support suricatta module is better implemented in Lua or C, > with their respective pros and cons. +1 > > >>> To get a bit more technical, the generic Lua suricatta module to be >>> written in C exposes a register() function to the Lua realm so that the >>> suricatta interface methods (include/suricatta/server.h) can be >>> implemented in Lua, >> >> Ok - so the polling server (suricatta.c) can call the specific backend >> implementation, that is in Lua if so specified. > > Yes, exactly. > > >> I just like to have the same features we have now, for example streaming >> should still work with the Lua backend. > > Absolutely. Both should be on a par. > Ok, we are perfectly in sync ! > >>> alongside a few other wrappers in order to call >>> SWUpdate (core) functionality from within the Lua realm to, e.g., handle >>> persistent state and doing communication. Again, the same story as with >>> the Lua handlers. >>> Currently, the `swupdate_suricatta.lua` Lua module looks like this: >>> ```lua >>> local suricatta = { >>> sleep = function(seconds) end, >>> install = function(ichannel, pchannel) end, >>> download = function(ichannel, pchannel, path) end, >>> get_tmpdir = function() end, >>> } >>> >>> suricatta.status = { >>> OK = 0, >>> EERR = 1, >>> EBADMSG = 2, >>> EINIT = 3, >>> EACCES = 4, >>> EAGAIN = 5, >>> UPDATE_AVAILABLE = 6, >>> NO_UPDATE_AVAILABLE = 7, >>> UPDATE_CANCELED = 8, >>> ID_REQUESTED = 9, >>> } >>> >>> suricatta.notify = { >>> error = function(message) end, >>> trace = function(message) end, >>> debug = function(message) end, >>> info = function(message) end, >>> warn = function(message) end, >>> progress = function(message) end, >>> } >>> >>> suricatta.pstate = { >>> get = function() end, >>> save = function(state) end, >>> reset = function() end, >>> OK = '0', >>> INSTALLED = '1', >>> TESTING = '2', >>> FAILED = '3', >>> NOT_AVAILABLE = '4', >>> ERROR = '5', >>> WAIT = '6', >>> IN_PROGRESS = '7', >>> } >>> >>> suricatta.server = { >>> register = function(name, functiont) end, >>> HAS_PENDING_ACTION = 0, >>> INSTALL_UPDATE = 1, >>> SEND_TARGET_DATA = 2, >>> GET_POLLING_INTERVAL = 3, >>> SERVER_START = 4, >>> SERVER_STOP = 5, >>> IPC = 6, >>> PRINT_HELP = 7, >>> } >>> >>> suricatta.channel = { >>> open = function(optiont) >>> return { >>> get = function(options) end, >>> install = function(options) end, >>> downloadonly = function(options, path) end, >>> put = function(options) end, >>> close = function() end, >>> } >>> end, >>> content = { >>> NONE = 0, >>> JSON = 1, >>> RAW = 2, >>> }, >>> method = { >>> GET = 0, >>> POST = 1, >>> PUT = 2, >>> PATCH = 3, >>> } >>> } >>> >>> return suricatta >>> ``` > > Gruss, Stefano
diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c index 5142c71..6521850 100644 --- a/corelib/channel_curl.c +++ b/corelib/channel_curl.c @@ -767,7 +767,7 @@ static channel_op_res_t parse_reply(channel_data_t *channel_data, output_data_t return CHANNEL_OK; } -static channel_op_res_t channel_post_method(channel_t *this, void *data) +static channel_op_res_t channel_post_method(channel_t *this, void *data, int method) { channel_curl_t *channel_curl = this->priv; assert(data != NULL); @@ -793,20 +793,29 @@ static channel_op_res_t channel_post_method(channel_t *this, void *data) goto cleanup_header; } - if ((curl_easy_setopt(channel_curl->handle, CURLOPT_POST, 1L) != CURLE_OK) || - (curl_easy_setopt(channel_curl->handle, CURLOPT_POSTFIELDS, - channel_data->request_body) != CURLE_OK)) { + CURLcode curl_result; + if (method == CHANNEL_PATCH) { + curl_result = curl_easy_setopt(channel_curl->handle, CURLOPT_CUSTOMREQUEST, "PATCH"); + } else { + curl_result = curl_easy_setopt(channel_curl->handle, CURLOPT_POST, 1L); + } + if (curl_result != CURLE_OK) { + result = CHANNEL_EINIT; + ERROR("Set POST/PATCH channel method option failed."); + goto cleanup_header; + } + if (curl_easy_setopt(channel_curl->handle, CURLOPT_POSTFIELDS, channel_data->request_body) != CURLE_OK) { result = CHANNEL_EINIT; - ERROR("Set POST channel method option failed."); + ERROR("Set POST/PATCH channel data option failed."); goto cleanup_header; } if (channel_data->debug) { - TRACE("Posted to %s: %s", channel_data->url, channel_data->request_body); + TRACE("POSTed/PATCHed to %s: %s", channel_data->url, channel_data->request_body); } CURLcode curlrc = curl_easy_perform(channel_curl->handle); if (curlrc != CURLE_OK) { - ERROR("Channel put operation failed (%d): '%s'", curlrc, + ERROR("Channel POST/PATCH operation failed (%d): '%s'", curlrc, curl_easy_strerror(curlrc)); result = channel_map_curl_error(curlrc); goto cleanup_header; @@ -908,9 +917,10 @@ channel_op_res_t channel_put(channel_t *this, void *data) case CHANNEL_PUT: return channel_put_method(this, data); case CHANNEL_POST: - return channel_post_method(this, data); + case CHANNEL_PATCH: + return channel_post_method(this, data, channel_data->method); default: - TRACE("Channel method (POST, PUT) is not set !"); + TRACE("Channel method (POST, PUT, PATCH) is not set !"); return CHANNEL_EINIT; } } diff --git a/include/channel_curl.h b/include/channel_curl.h index 6b4f4da..c3418a5 100644 --- a/include/channel_curl.h +++ b/include/channel_curl.h @@ -25,6 +25,7 @@ typedef enum { CHANNEL_GET, CHANNEL_POST, CHANNEL_PUT, + CHANNEL_PATCH, } channel_method_t; typedef enum {
Signed-off-by: Christian Storm <christian.storm@siemens.com> --- corelib/channel_curl.c | 28 +++++++++++++++++++--------- include/channel_curl.h | 1 + 2 files changed, 20 insertions(+), 9 deletions(-)