RuntimeError: headers have already been sent

11 views
Skip to first unread message

Velu Narasimman

unread,
Mar 12, 2020, 9:58:34 AM3/12/20
to Trac Users
Hi,

    I wish to re-open the same topic from here. I am ready to share my code here as well.

    Client side code below

        $.savePermissions = function(user_roles,new_roles) {
           
params = { 'change' : true, 'user_roles' : user_roles, 'new_roles':new_roles };

           
var href = window.location.pathname;
            $
(".ui-wait").show();
            $
.ajax({
                type
: "POST",
                url
: href,
                data
: params,
                dataType
: "json",
                success
: function (data) {
            console
.log(data);
                   
if ( data.errors.length ) {
                        $
.addWarnings(data.errors);
                   
}
                   
else if ( data.notices.length ) {
                        $
.addNotices(data.notices);
                       
}

                    $
(".ui-wait").hide();
               
},
                error
: function (jqXHR, exception,errorThrown) {
                    console
.log(errorThrown);
                    $
.addWarnings(["Error in updating permissions"]);
                    $
(".ui-wait").hide();
               
}
           
});
       
};

That ajax call is failing sometimes. But the RuntimeError occurs even if the ajax call is success. I found the error is logged in log file.

    Server side code below

            if req.args.get('change'):
               
try:
                    accounts
= [token.split('|')
                                       
for token in get_list_on_scalar(req.args.get('user_roles'))
                                                       
if token]
                   
for username, role in accounts:
                        userrole
= req.args.get("new_roles").split(',');
                       
if not userrole:
                            add_warning
(req, "There was some problem in getting role preference for user - %s, failed to proceed." % username)
                            errors
.append("There was some problem in getting role preference for user - %s, failed to proceed." % username)
                       
else:
                           
# account_manager.modify_role(req, username, userrole)
                           
# add_notice(req, "The user  roles are updated")
                           
# notices.append("The user - %s role %s have been updated"% (username, ','.join(userrole)))
                            notices
.append("Role of user - '%s' is updated as '%s'"% (username, ','.join(userrole)))
                            data
['notices'] = notices
                            data
['errors'] = errors
                            message
= "The user - %s role %s have been updated" % (username, userrole)
                           
EventLogManagement(self.env).log_event(req.authname, self.env.project_name, Modules.ADMIN, message, req.remote_addr, Keys.INFO)
               
self.respond(req, data)

               
except:
                   
(self.log.debug(traceback.format_exception(*sys.exc_info())))
               
self.respond(req, data)

That respond method goes like this,

    def respond(self, req, data, code=200):
       
"""Respond to the JSON request by sending the JSON-encoded data back."""
        json_data
= json.dumps(data)
       
self.env.log.debug("JS_on")
       
self.env.log.debug(json_data)
        req
.send_response(code)
        req
.send_header('Content-Type', 'application/json')
        req
.send_header('Content-Length', len(json_data))
        req
.write(json_data)
       
raise RequestDone


Basically what I am doing here is, getting some data from the user and storing it to database. Returning a json response back to browser. The problem is, save operations is not properly done. after the ajax is over, my understanding is the save action is done. So I refreshed the page but my page showed me the previous state of the page. I am confused here!

    It would be better if I can get a clear sample of how one should make the ajax call properly in trac.

Jun Omae

unread,
Mar 12, 2020, 10:46:56 AM3/12/20
to trac-...@googlegroups.com
On Thu, Mar 12, 2020 at 10:58 PM Velu Narasimman <velava...@gmail.com> wrote:
> That ajax call is failing sometimes. But the RuntimeError occurs even if the ajax call is success. I found the error is logged in log file.
>
> Server side code below
>
> if req.args.get('change'):
> try:
> accounts = [token.split('|')
> for token in get_list_on_scalar(req.args.get('user_roles'))
> if token]
> for username, role in accounts:
> userrole = req.args.get("new_roles").split(',');
> if not userrole:
> add_warning(req, "There was some problem in getting role preference for user - %s, failed to proceed." % username)
> errors.append("There was some problem in getting role preference for user - %s, failed to proceed." % username)
> else:
> # account_manager.modify_role(req, username, userrole)
> # add_notice(req, "The user roles are updated")
> # notices.append("The user - %s role %s have been updated"% (username, ','.join(userrole)))
> notices.append("Role of user - '%s' is updated as '%s'"% (username, ','.join(userrole)))
> data['notices'] = notices
> data['errors'] = errors
> message = "The user - %s role %s have been updated" % (username, userrole)
> EventLogManagement(self.env).log_event(req.authname, self.env.project_name, Modules.ADMIN, message, req.remote_addr, Keys.INFO)
> self.respond(req, data) # <=== 1st call
>
> except:
> (self.log.debug(traceback.format_exception(*sys.exc_info())))
> self.respond(req, data) # <=== 2nd call

The respond() method is called twice. It means Request.end_headers()
is called twice via Request.write().

RequestDone shouldn't be caught.

> except:
> (self.log.debug(traceback.format_exception(*sys.exc_info())))

The except block should be removed or the exception should be re-raise
like this:

except:

(self.log.debug(traceback.format_exception(*sys.exc_info())))
raise # <== add this line

Also, the following line:
(self.log.debug(traceback.format_exception(*sys.exc_info())))
could be:
self.log.debug('Exception caught', exc_info=True)

--
Jun Omae <jun...@gmail.com> (大前 潤)

Velu Narasimman

unread,
Mar 13, 2020, 5:32:29 AM3/13/20
to Trac Users
Thank you Jun Omae. I removed one call to "respond" method and now it is working fine. Thanks for your help!
Reply all
Reply to author
Forward
0 new messages