I have just started seeing an ineresting problem with program I have been using to talk to a REST API for the past year or more. In particular sometime very recently the indicies in the "meta()" array populated
after a geturl request have started, sometimes, being populated in
lower case. It's not consistent, so I suspect my requests are being round-robined across different servers, but to give a particular
example, I had been doing something like:
if {[string match -nocase {application/json*} $meta(Content-Type)]} {
whatever
}
and now I am finding that sometimes "meta(Content-Type)" does not exist, but "meta(content-type)" does. Googling around I'm seeing that apparently servers are allowed to do this, but the meta() array seems almost useless
if this is going to happen.
Ted Nolan <tednolan> <[email protected]> wrote:
I have just started seeing an ineresting problem with program I have been
using to talk to a REST API for the past year or more. In particular
sometime very recently the indicies in the "meta()" array populated
after a geturl request have started, sometimes, being populated in
lower case. It's not consistent, so I suspect my requests are being
round-robined across different servers, but to give a particular
example, I had been doing something like:
if {[string match -nocase {application/json*} $meta(Content-Type)]} { >> whatever
}
and now I am finding that sometimes "meta(Content-Type)" does not exist, but >> "meta(content-type)" does. Googling around I'm seeing that apparently
servers are allowed to do this, but the meta() array seems almost useless
if this is going to happen.
some random thoughts...
1.) Is Content-Type the only such field, or could this thing happen
for any other http-header?
2.) What's happening with headers that are allowed to occur multiple
times? would these also be allowed to appear in different casings?
If Content-Type is the only one, and all-lowercase "content-type" the
only variant of it, then the workaround would be straightforward:
if {![info exists meta(Content-Type)]} { set meta(Content-Type)
$meta(content-type) }
Otherwise, you might need to loop over the keys of meta, and just
set a lowercase version of each key with original value in a new
array.
I have just started seeing an ineresting problem with program I have been using to talk to a REST API for the past year or more. In particular sometime very recently the indicies in the "meta()" array populated
after a geturl request have started, sometimes, being populated in
lower case. It's not consistent, so I suspect my requests are being round-robined across different servers, but to give a particular
example, I had been doing something like:
if {[string match -nocase {application/json*} $meta(Content-Type)]} {
whatever
}
and now I am finding that sometimes "meta(Content-Type)" does not exist, but "meta(content-type)" does. Googling around I'm seeing that apparently servers are allowed to do this, but the meta() array seems almost useless
if this is going to happen. I can fix the program of course, I guess
looking at the man page, I should probably just check "state(type)",
instead. Should the "meta()" subscripts be lowercased in future
versions, or should there be a warning on the man page not to use them
other than for debugging?
On 18/08/2023 20:29, Ted Nolan <tednolan> wrote:
This is just one of several issues with the http package that prompted
me to develop the www package (https://chiselapp.com/user/schelte/repository/www)
On 8/19/2023 4:01 AM, Schelte wrote:
On 18/08/2023 20:29, Ted Nolan <tednolan> wrote:
This is just one of several issues with the http package that prompted
me to develop the www package
(https://chiselapp.com/user/schelte/repository/www)
This looks like a comprehensive and a well thought-out package. I read
a little bit of the documentation and may I kindly make a comment for
your consideration:
It says that it uses an in-memory sqlite database for managing cookies.
That sounds good but at the same time, this choice may interfere with
user scripts that use sqlite for their own purposes.
Can you load
multiple different versions of sqlite simultaneously?
Is it thread-safe?
I am not sure.
In any case, this would easily result in your package and user scripts
to fall out of sync with respect to sqlite versions they need.
IMO, sqlite use here is not really needed. I think for the purposes you
need it for, a plain dictionary might do the job here, which would make
the package more attractive.
On 8/19/2023 4:01 AM, Schelte wrote:
On 18/08/2023 20:29, Ted Nolan <tednolan> wrote:
This is just one of several issues with the http package that prompted
me to develop the www package
(https://chiselapp.com/user/schelte/repository/www)
This looks like a comprehensive and a well thought-out package. I read
a little bit of the documentation and may I kindly make a comment for
your consideration:
It says that it uses an in-memory sqlite database for managing cookies.
That sounds good but at the same time, this choice may interfere with
user scripts that use sqlite for their own purposes. Can you load
multiple different versions of sqlite simultaneously? Is it thread-safe?
I am not sure.
In any case, this would easily result in your package and user scripts
to fall out of sync with respect to sqlite versions they need.
IMO, sqlite use here is not really needed. I think for the purposes you
need it for, a plain dictionary might do the job here, which would make
the package more attractive.
The www package is happy to use the same version of sqlite3 that may be required by other parts of the application. It doesn't use any advanced features that require the latest sqlite3 version.
Using plain dicts would have required a lot of extra code to do things
that can easily be done with sqlite, like searching based on different
items and storing the information on disk.
For example: Assuming a dict would be keyed on origin, then path, and
finally cookie name, the whole dict would have to be examined to find
expired cookies. Or can you suggest a directory structure that would
make that easier?
For storing cookies between application runs, it is of course possible
to simply dump the dict as a string to file. But then checks and error handling would have to be added when reading it back.
Since sqlite makes all of these tasks easier and it comes bundled with
Tcl anyway, I chose to make use of it. You haven't yet persuaded me to reverse that decision.
On 18/08/2023 20:29, Ted Nolan <tednolan> wrote:
I have just started seeing an ineresting problem with program I have been
using to talk to a REST API for the past year or more. In particular
sometime very recently the indicies in the "meta()" array populated
after a geturl request have started, sometimes, being populated in
lower case. It's not consistent, so I suspect my requests are being
round-robined across different servers, but to give a particular
example, I had been doing something like:
if {[string match -nocase {application/json*} $meta(Content-Type)]} { >> whatever
}
and now I am finding that sometimes "meta(Content-Type)" does not exist, but >> "meta(content-type)" does. Googling around I'm seeing that apparently
servers are allowed to do this, but the meta() array seems almost useless
if this is going to happen. I can fix the program of course, I guess
looking at the man page, I should probably just check "state(type)",
instead. Should the "meta()" subscripts be lowercased in future
versions, or should there be a warning on the man page not to use them
other than for debugging?
This is just one of several issues with the http package that prompted
me to develop the www package >(https://chiselapp.com/user/schelte/repository/www)
Schelte.
I have just started seeing an ineresting problem with program I have been using to talk to a REST API for the past year or more. In particular sometime very recently the indicies in the "meta()" array populated
after a geturl request have started, sometimes, being populated in
lower case. It's not consistent, so I suspect my requests are being round-robined across different servers, but to give a particular
example, I had been doing something like:
if {[string match -nocase {application/json*} $meta(Content-Type)]} {
whatever
}
and now I am finding that sometimes "meta(Content-Type)" does not exist, but "meta(content-type)" does. Googling around I'm seeing that apparently servers are allowed to do this, but the meta() array seems almost useless
if this is going to happen. I can fix the program of course, I guess
looking at the man page, I should probably just check "state(type)",
instead. Should the "meta()" subscripts be lowercased in future
versions, or should there be a warning on the man page not to use them
other than for debugging?
Hi Ted,
I hadn't noticed this incorrect information in the man page for Tcl 8.6.
Also the 8.6 man page unhelpfully suggests using
array set meta $state(meta)
The case-sensitivity issue is fixed in Tcl 8.7, and I believe the >documentation in 8.7 is accurate. When upgrading from 8.6 to 8.7 users
may need to alter their scripts to use the new commands and/or adjust
how they use the "meta" internal state. Tcl 8.6 and 8.7 handle these
issues differently.
The changes you describe sound nice, and I look forward to seeing Tcl
8.7 in our linux distro package managers! Unfortunately that may
take a while as our mix of distros is quite diverse.
In article <[email protected]>,
Keith Nash <[email protected]> wrote:
Thanks for the info Keith!
Hi Ted,
I hadn't noticed this incorrect information in the man page for Tcl 8.6.
Also the 8.6 man page unhelpfully suggests using
array set meta $state(meta)
Which is what I was doing & why :-)
The case-sensitivity issue is fixed in Tcl 8.7, and I believe the
documentation in 8.7 is accurate. When upgrading from 8.6 to 8.7 users
may need to alter their scripts to use the new commands and/or adjust
how they use the "meta" internal state. Tcl 8.6 and 8.7 handle these
issues differently.
The changes you describe sound nice, and I look forward to seeing Tcl 8.7
in our linux distro package managers! Unfortunately that may take a
while as our mix of distros is quite diverse.
Regards,
Ted Nolan
I am not sure it is a good idea, by default, to maintain state between repeated runs of the user program.
On 21/08/2023 01:53, saitology9 wrote:
I am not sure it is a good idea, by default, to maintain state between
repeated runs of the user program.
I agree. That's why it doesn't do it by default. But it provides the possibility, if you want it.
Elsewhere in the thread, someone mentioned that 8.7 adds a cookiejar
package for handling cookies for the http package. And guess what? It
uses an sqlite database to store the cookies.
Schelte.
On 23/08/2023 19:08, Schelte wrote:
On 21/08/2023 01:53, saitology9 wrote:May I offer an observation and a suggestion that I fear is so obvious
I am not sure it is a good idea, by default, to maintain state between
repeated runs of the user program.
I agree. That's why it doesn't do it by default. But it provides the
possibility, if you want it.
Elsewhere in the thread, someone mentioned that 8.7 adds a cookiejar
package for handling cookies for the http package. And guess what? It
uses an sqlite database to store the cookies.
Schelte.
that it's already been considered and discarded?
I assume that the packages being discussed open a memory-only sqlite3 database by opening :memory:. This seems to me to risk interfering
with an application that also wants an in-memory sqlite database.
[snip]
Please be gentle as you explain why this is a rotten suggestion.
So opening :memory: would seem to be safe (to the extent that someone
does not explicitly write code to go fish the 'cookie jar' db handle out
of the loaded module). Now, whether this is /documented/ behavior or
just a happy side effect I have not researched.
Elsewhere in the thread, someone mentioned that 8.7 adds a cookiejar
package for handling cookies for the http package. And guess what? It
uses an sqlite database to store the cookies.
May I offer an observation and a suggestion that I fear is so obvious
that it's already been considered and discarded?
I assume that the packages being discussed open a memory-only sqlite3 database by opening :memory:. This seems to me to risk interfering with
an application that also wants an in-memory sqlite database.
Would it not be better to use a disk-based database with published name
and location that an application writer can choose to interfere with or, preferably, to keep well clear of?
On 8/23/2023 3:15 PM, Alan Grunwald wrote:
May I offer an observation and a suggestion that I fear is so obvious
that it's already been considered and discarded?
I assume that the packages being discussed open a memory-only sqlite3
database by opening :memory:. This seems to me to risk interfering with
an application that also wants an in-memory sqlite database.
You make a great point above. It seems to a non-issue but this is just another risk.
It turns out it is not. In message
<nnd$36affa55$0b276155@764ea9c06e9f0d0b> is a quote from the Sqlite
docs where it is documented that each DB handle open on the :memory:
pseudo file results in a fully separate database.
So there is no chance of accidental interference.
The only interference possibility is deliberate interference where an
author deliberately introspected the http module to extract the db
handle name in order to access the cookie database.
Given that sqlite ships as a built in part of Tcl (and has starting
with 8.6), calling a Tcl script only package that uses the built in sqlite
a "binary extension" is a stretch.
On 8/23/2023 2:08 PM, Schelte wrote:
Elsewhere in the thread, someone mentioned that 8.7 adds a cookiejar
package for handling cookies for the http package. And guess what?
It uses an sqlite database to store the cookies.
So, it too is a binary package then. No problem there. But it
doesn't change how I feel about binary extensions.
I am not so sure. Have you considered user script transactions (e.g.,
looping over a bunch of url's) vs. the package transactions (i.e.,
saving thee cookies)?
From sqlite docs:
"SQLite supports multiple simultaneous read transactions coming from **separate database connections**, possibly in separate threads or
processes, **but only one simultaneous write transaction**."
On 8/23/2023 11:31 PM, Rich wrote:
Given that sqlite ships as a built in part of Tcl (and has starting
with 8.6), calling a Tcl script only package that uses the built in sqlite >> a "binary extension" is a stretch.
Well, sqlite is not loaded by default. To use it, you need to load it.
So it fits the package or extension criterion. And it is binary. QED :-)
On 8/23/2023 11:34 PM, Rich wrote:
It turns out it is not. In message
<nnd$36affa55$0b276155@764ea9c06e9f0d0b> is a quote from the Sqlite
docs where it is documented that each DB handle open on the :memory:
pseudo file results in a fully separate database.
So there is no chance of accidental interference.
The only interference possibility is deliberate interference where an
author deliberately introspected the http module to extract the db
handle name in order to access the cookie database.
I am not so sure. Have you considered user script transactions (e.g.,
looping over a bunch of url's) vs. the package transactions (i.e.,
saving thee cookies)?
From sqlite docs:
"SQLite supports multiple simultaneous read transactions coming from **separate database connections**, possibly in separate threads or
processes, **but only one simultaneous write transaction**."
Perhaps you could write a small program to test it. Would be
interesting to find out.
On 23/08/2023 23:35, Rich wrote:
So opening :memory: would seem to be safe (to the extent that someone
does not explicitly write code to go fish the 'cookie jar' db handle
out of the loaded module). Now, whether this is /documented/ behavior
or just a happy side effect I have not researched.
It is documented behavior. https://www.sqlite.org/inmemorydb.html says: "Every :memory: database is distinct from every other. So, opening two database connections each with the filename ":memory:" will create two independent in-memory databases."
Schelte.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 18:17:06 |
| Calls: | 12,103 |
| Calls today: | 3 |
| Files: | 15,004 |
| Messages: | 6,518,081 |