Modify the body in a HTTP post

1,289 views
Skip to first unread message

Trond Andersen

unread,
Sep 12, 2013, 7:37:10 AM9/12/13
to cefs...@googlegroups.com
I see the IRequest.Body property is only a read-only property. Is it possible to do modification to the Body in the post before sending it to the server? Is there an alternative way to modify the request slightly before sending it?

We currently have the need to add some additional information to a text field in the body. A work colleague was able to do such modification on Mac OS X by replacing the request object with a mutable request object.

Any thoughts?

Per Lundberg

unread,
Sep 12, 2013, 5:02:45 PM9/12/13
to cefs...@googlegroups.com
Hi,

Unfortunately, I think the easiest way to get this done is by using a custom scheme handler, where you basically override the default HTTP handler. I did something similar some week ago to get NTLM/Kerberos authentication working properly (because of stupidity with Microsoft Reporting Services...).

Check the CefSharp.Example project for a sample scheme handler.

Best regards,
Per

Trond Andersen

unread,
Sep 13, 2013, 3:46:35 AM9/13/13
to cefs...@googlegroups.com
Hi again.  
Unfortunately, I think the easiest way to get this done is by using a custom scheme handler, where you basically override the default HTTP handler. I did something similar some week ago to get NTLM/Kerberos authentication working properly (because of stupidity with Microsoft Reporting Services...).

Check the CefSharp.Example project for a sample scheme handler.
I see from the sample code that this also focus on returning "self-generated" content before the request is sent to the server. The parameters to the method sends a IRequest which has an immutable body property. I wonder how you are able to modify the request when the body part is immutable. Is it possible to show an example where this is done? I guess I could create a request object for myself, but the instance of the IRequest object is an CefRequestWrapper and that class is not accessible from application code. Can I replace the IRequest reference with my own IRequest implementation?

Sorry for all the questions, but I struggle a bit with getting the whole picture here.


Best regards,
Trond

richard Boyewa

unread,
Sep 15, 2013, 12:25:46 AM9/15/13
to cefs...@googlegroups.com
@per,I think i am lost on the Cef3 to .Net project. Does it support webrtc yet?

Good job so far fello hackers :-)
> --
> You received this message because you are subscribed to the Google Groups "CefSharp" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to cefsharp+u...@googlegroups.com.
> To post to this group, send email to cefs...@googlegroups.com.
> Visit this group at http://groups.google.com/group/cefsharp.
> For more options, visit https://groups.google.com/groups/opt_out.
>

--
'Boyewa Richard
(Coordinator / Team Lead, Software Engineering Lab, CoEx OAU)

Trond Andersen

unread,
Sep 16, 2013, 5:36:22 AM9/16/13
to cefs...@googlegroups.com


Unfortunately, I think the easiest way to get this done is by using a custom scheme handler, where you basically override the default HTTP handler. I did something similar some week ago to get NTLM/Kerberos authentication working properly (because of stupidity with Microsoft Reporting Services...).

I've been looking at the C++ API for Cef 1.25 and found that (at least from what I can see) the corresponding CefRequest object has a SetPostData method. Any reason why this method is not exposed in CefSharp? By exposing this method I think that my need for modifying the body part would be fixed.

Per Lundberg

unread,
Sep 16, 2013, 5:38:33 AM9/16/13
to cefs...@googlegroups.com
Hi,

Please start a separate thread for this, instead of hijacking another one with a different subject... :P

Best regards,
Per

Per Lundberg

unread,
Sep 16, 2013, 5:40:30 AM9/16/13
to cefs...@googlegroups.com
Hi Trond,

(Sorry for not answering to your previous one, have been too busy with "real life"/AFK activities lately.)

My idea was that you would perform the request yourself (using a SchemeHandler); i.e. send the request to the remote using a WebClient or similar. This is a bit of work, but it can clearly be done; I've done it myself a few weeks ago.

However, your idea with the CefRequest->SetPostData() might be a simpler and better way in this case. Please feel free to investigate it further and submit a pull request, and we can then try to get it incorporated into the main repo.

Best regards,
Per

Trond Andersen

unread,
Sep 17, 2013, 4:31:47 AM9/17/13
to cefs...@googlegroups.com
Hi Per.

My idea was that you would perform the request yourself (using a SchemeHandler); i.e. send the request to the remote using a WebClient or similar. This is a bit of work, but it can clearly be done; I've done it myself a few weeks ago.
A more elaborate example demonstrating how this could be done would be beneficial. I don't see a solution for my needs based on the simple example provided with CefSharp. 

However, your idea with the CefRequest->SetPostData() might be a simpler and better way in this case. Please feel free to investigate it further and submit a pull request, and we can then try to get it incorporated into the main repo.
I tried to get CefSharp up and running on my computer, but it won't start. I've looked at the recent update to the wiki page, but I still was not able to run CefSharp.WinForms.Example or CefSharp.Wpf.Example based on the master branch.

I have never tried to implement anything in C++, but tried to have a naive implementation of the setter for the Body property:

void CefRequestWrapper::Body::set(String^ postdata)
{
if (postdata != nullptr)
{
CefString data = toNative(postdata);
CefRefPtr<CefPostData> nativePostdata(CefPostData::CreatePostData());
CefRefPtr<CefPostDataElement> element(CefPostDataElement::CreatePostDataElement());

element->SetToBytes(sizeof(data), data.ToWString().data());
nativePostdata->AddElement(element);

_wrappedRequest->SetPostData(nativePostdata);
}  
}

Since I didn't get the example projects to run, it was a bit difficult to test this.

Per Lundberg

unread,
Sep 17, 2013, 5:49:13 AM9/17/13
to cefs...@googlegroups.com
Hi,

Sorry to hear about your trouble. What errors do you get when you try to run the samples? Are you using VS2010 or 2012?

Regarding the scheme handler - there is no public example of that at the moment, unfortunately. The one I did was for the company where I work and I'm not sure it can be released as open source at this time. All in all, it seems overkill for your use case anyway.

Best regards,
Per

Trond Andersen

unread,
Sep 17, 2013, 7:45:03 AM9/17/13
to cefs...@googlegroups.com
Hi,
Sorry to hear about your trouble. What errors do you get when you try to run the samples? Are you using VS2010 or 2012?
I'm using VS2012 update 3. I will probably get this to work - just need to finger out the reason for the error message.

Do you think I am on the right path with regards to the implementation of the setter of the body property?

Best Regards,
Trond Andersen

Per Lundberg

unread,
Sep 17, 2013, 4:44:40 PM9/17/13
to cefs...@googlegroups.com
Hi,

Yes, I guess so. You should probably not ignore postdata == nullptr though, but instead clear the body or something like that. But yeah, I guess something quite close to this could work (but to be honest, I really don't know so much about the CEF internals in this area).

Best regards,
Per

Trond Andersen

unread,
Sep 18, 2013, 3:25:54 PM9/18/13
to cefs...@googlegroups.com

Yes, I guess so. You should probably not ignore postdata == nullptr though, but instead clear the body or something like that.
Agreed.
 
But yeah, I guess something quite close to this could work (but to be honest, I really don't know so much about the CEF internals in this area).
 I've struggeled getting the CefString containing the new body post into the CefPostDataElement with the SetToBytes method. 

If I did a hack like this:

void CefRequestWrapper::Body::set(String^ postdata)
{
if (postdata != nullptr)
{
CefString file = "c:\\temp\\cefPostData.txt";

CefRefPtr<CefPostData> nativePostdata(CefPostData::CreatePostData());
CefRefPtr<CefPostDataElement> element(CefPostDataElement::CreatePostDataElement());

element->SetToFile(file);
nativePostdata->AddElement(element);

_wrappedRequest->SetPostData(nativePostdata);
        }
}

The temporary file contained a simple body post content and the server receives the modified post.If you got any pointers on how to convert a CefString to a char array correctly then I guess this would probably work.

Per Lundberg

unread,
Sep 19, 2013, 1:43:02 AM9/19/13
to cefs...@googlegroups.com
Hi,

Did a quick test: perhaps something like this would do? It worked for me <tm>. However, please note that this will not work at all if your body contains non-ASCII (like Swedish åäö characters, or your Danish/Norwegian counterparts).

    CefString cefStr = "gurka";
    const wchar_t* wcharStr = cefStr.c_str();
    auto charStr = (char*)malloc(256); // note! must deallocate at some point...
    wcstombs(charStr, wcharStr, 256);

Of course, the point about the deallocation is also quite crucial. :)

Best regards,
Per 

Trond Andersen

unread,
Sep 19, 2013, 3:46:42 AM9/19/13
to cefs...@googlegroups.com
I modified the code to the following:

CefRefPtr<CefPostData> nativePostdata(CefPostData::CreatePostData());

if (postdata != nullptr)
{
CefString data = toNative(postdata);
size_t length = data.size();
std::string bytes = data.ToString();

CefRefPtr<CefPostDataElement> element(CefPostDataElement::CreatePostDataElement());

element->SetToBytes(length, bytes.c_str());
nativePostdata->AddElement(element);
}

_wrappedRequest->SetPostData(nativePostdata);

The server gets the modified body, but I'm a bit unsure with memory deallocation. Trying to call free(element) or free(&bytes) resulted in error messages. If I understand size_t correct, I don't have to dealloc that. Any pointers on how to clean up memory in this method for a complete C++ novice would be appreciated.


-- 
Trond

Per Lundberg

unread,
Sep 19, 2013, 4:01:15 PM9/19/13
to cefs...@googlegroups.com
Hi,

Let us go through that code in detail, as far as the memory allocation is concerned.

1) The conversion to a CefString - should be safe, since we only get a CefString object (which is stored on the stack, and essentially passed/returned by value, if I remember correctly). No memory leak there.

2) The size_t object - yes, that's basically an integer and is also stored on the stack. Stack variables are automatically deallocated when the method returns; but this also means that it's important to NOT pass a pointer to them into another method, for example.

3) The std::string bytes. Should also be OK, since it's a stack variable.

4) The CefPostDataElement - should be OK. CefRefPtr is a bit "magic" in that it's a ref-counted structure, which means that you actually can pass it around. The object is allocated (using new/delete or malloc/free, which are basically the same things in C++ and C respectively) on the heap - not on the stack - but the CefRefPtr makes sure it only lives as long as someone references it. If all references go out of scope, or are set to nullptr, the object gets automatically freed.

I would say the dangerous part here seems like this line:

element->SetToBytes(length, bytes.c_str());

This gets a reference to the internal char array in the "bytes" std::string object. However, the "bytes" object runs out of scope a few lines later. That seems risky; when "bytes" no longer exists, the reference to the c_str() value will no longer be valid. This could be a source of error.

However, again, when I read the comment (in cef_request.h) for the SetToBytes() method, I see this:

  ///
  // The post data element will represent bytes.  The bytes passed
  // in will be copied.
  ///
  /*--cef()--*/
  virtual void SetToBytes(size_t size, const void* bytes) =0;

...so if the bytes are copied, we should be safe. I believe your code is good, from how I understand it.

Best regards,
Per

Czarek Tomczak

unread,
Sep 19, 2013, 10:35:46 PM9/19/13
to cefs...@googlegroups.com
Hi,

Everything what Per has written looks good.

In C++ you don't have to worry about freeing memory unless you're using:
1) the new keyword 
2) the * pointer
3) the malloc/calloc functions

Also when using CefRefPtr (the smart reference counted pointer, see the Smart Pointer wikipedia
page) you don't have to worry about freeing memory even if you instantiated the class on the heap 
using the new keyword:

CefRefPtr<SomeClass> some = new SomeClass();

CEF will free it automatically.

Best regards,
Czarek

Trond Andersen

unread,
Sep 20, 2013, 8:30:04 AM9/20/13
to cefs...@googlegroups.com
Hi Per.

Thank you for the thorough answer. Great to get the reasoning.

...so if the bytes are copied, we should be safe. I believe your code is good, from how I understand it.

Would like this as a pull request + github issue? I haven't created any example code in WinForms/WPF example project. If you want that I will have to create that a bit later - I also need a reliable service to invoke a post against and preferable echos the body content. I have not looked at the unit tests so I don't know the effort needed here.

 
Regards,
Trond Andersen

Per Lundberg

unread,
Sep 20, 2013, 3:50:29 PM9/20/13
to cefs...@googlegroups.com
Hi,

Yes, a pull request for this would be nice & appreciated! :) You don't have to provide an example, but of course I wouldn't mind if you do...

As for a reliable server for testing POST requests - this one seems nice! http://httpbin.org/post
They have a plethora of other test URLs we could possibly also benefit from if/when we need.

Best regards,
Per

Trond Andersen

unread,
Oct 3, 2013, 7:53:07 AM10/3/13
to cefs...@googlegroups.com

Yes, a pull request for this would be nice & appreciated! :) You don't have to provide an example, but of course I wouldn't mind if you do...

As for a reliable server for testing POST requests - this one seems nice! http://httpbin.org/post
They have a plethora of other test URLs we could possibly also benefit from if/when we need.

The trouble with using httpbin.org/post is that I really need a form in which the user can input text and then see that CefSharp has modified the post with added information. Posting directly to the post url does not give the same effect. I have created an issue in the httpbin project regarding this.

I see that a version 1.25.5 is coming up. Any possibility to add this small change without an example?


Per Lundberg

unread,
Oct 4, 2013, 5:10:17 PM10/4/13
to cefs...@googlegroups.com
Hi,

This is trivial to fix on our end. We can just set up
a test page as an embedded resource (using the custom scheme handler and just put a <form> there, which posts to httpbin. Do you see what I mean?

Regarding 1.25.5, it's out; I just haven't updated GitHub and added binaries. I needed it for work (the fixed drop down issue), so that's why it got done. But we can definitely release 1.25.6 ASAP, there might also be other people who have something neat coming up? :)

Per Lundberg

unread,
Oct 13, 2013, 2:58:51 PM10/13/13
to cefs...@googlegroups.com
Hi,

Did you manage to make a PR out of this? Let us know if you need any assistance in doing so.

Best regards,
Per



--
You received this message because you are subscribed to a topic in the Google Groups "CefSharp" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cefsharp/5d7x27Nb_TA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cefsharp+u...@googlegroups.com.

To post to this group, send email to cefs...@googlegroups.com.
Visit this group at http://groups.google.com/group/cefsharp.
For more options, visit https://groups.google.com/groups/opt_out.



--
mvh,
Per Lundberg

Trond Andersen

unread,
Oct 17, 2013, 8:28:14 AM10/17/13
to cefs...@googlegroups.com
Hi Per.

Did you manage to make a PR out of this? Let us know if you need any assistance in doing so.

 I have crazy times at work right now. As soon as it settles down a bit I will provide a pull request for this functionality which also includes the example functionality.


-- 
Trond

Nader Hamzei

unread,
Oct 17, 2013, 5:20:34 PM10/17/13
to cefs...@googlegroups.com
Hi Guys

I am having a similiar problem of needing to add to the request Body. did this get worked out?
is there a release that gives CEFSharp public access to setting the request body?

Thanks
Nader

Trond Andersen

unread,
Oct 18, 2013, 3:22:41 PM10/18/13
to cefs...@googlegroups.com
Yes it work. I've been using this on the project I'm currently working on. 

There are only a few changes needed. In IRequest.h modify the Body property:

property String^ Body { String^ get(); void set(String^ postData); }

The same in Request.h:

virtual property String^ Body { String^ get(); void set(String^ postData); }

And add the setter property to the implementation which is Request.cpp:

void CefRequestWrapper::Body::set(String^ postdata)
{
CefRefPtr<CefPostData> nativePostdata(CefPostData::CreatePostData());

if (postdata != nullptr)
{
CefString data = toNative(postdata);
size_t length = data.size();
std::string bytes = data.ToString();

CefRefPtr<CefPostDataElement> element(CefPostDataElement::CreatePostDataElement());

element->SetToBytes(length, bytes.c_str());
nativePostdata->AddElement(element);
//free(element);
}

_wrappedRequest->SetPostData(nativePostdata);
}

Thats it.

Øyvind Pedersen

unread,
Nov 20, 2014, 6:23:33 AM11/20/14
to cefs...@googlegroups.com
Will this ever be included into a CefSharp release? It would be nice if the IRequest had a setter on the Body property.

Trond Andersen

unread,
Feb 20, 2015, 4:58:37 AM2/20/15
to cefs...@googlegroups.com
On Thursday, 20 November 2014 12:23:33 UTC+1, Øyvind Pedersen wrote:
Will this ever be included into a CefSharp release? It would be nice if the IRequest had a setter on the Body property.

If a test was included to the test suite I would probably guess that the project would include the feature. I have a few thoughts on how this could be done   :-)


-- 
Trond 
Reply all
Reply to author
Forward
0 new messages