Arc Forumnew | comments | leaders | submit | lark's commentslogin

The test from the following link no longer works as expected after the fix. 0 bytes are saved.

http://arclanguage.org/item?id=16313

-----

1 point by akkartik 4737 days ago | link

Yes, good point. Since the server now processes POST bodies, you won't have access to the unparsed data. I'll update the webupload.arc example.

Update: a few bugfixes later you can see all the different kinds of forms in action here: http://github.com/nex3/arc/blob/cc0f448538/lib/form-tests.ar...

There's still one open question regarding filenames. So far we've been writing uploaded files to random filenames, but the uploaded filename is actually present in the POST request. I see 2 ways to provide it to the programmer (say when uploading a file in a field called file):

a) (arg req "file") returns just the contents of the uploaded file; the filename is in (arg req "filename"). "filename" is the multipart header, so I could just inline all the various headers into the args table.

b) (arg req "file") returns an alist or table with the various headers for that part of the multipart POST. File contents are in ((arg req "file") 'contents).

c) (arg req "file") returns file contents like in a, and other metadata like filename or creation-date is in some other field of req, say req!multipart.

b generalizes to multiple file uploads in a single form, but it's also a little more work to get at form input values. c addresses this but now you've got stuff for a field scattered in multiple places. What do people prefer?

-----

1 point by lark 4731 days ago | link

> Update: a few bugfixes later you can see all the different kinds of forms in action here: http://github.com/nex3/arc/blob/cc0f448538/lib/form-tests.ar...

Does the fnid multipart form test (the second test) and the static multipart test (the third test) work for you?

They do not work for me. I get a "srv thread took too long for <ip address>". I suspect this could be related to nginx again -- though, I started the webserver on a different port and run form-tests through that different port.

How come a non-multipart test works and a multipart test does not? Is there something going on with multipart and ports?

-----

1 point by akkartik 4731 days ago | link

Yeah they work for me. Can you try them without nginx?

It's possible nginx has some settings that are specific to multipart requests..

-----

1 point by lark 4731 days ago | link

You missed my point.

When testing multipart stuff, I start the app in a custom port -- not port 80. So it should not be talking to nginx at all.

Unless there's something in Anarki that makes it talk to it...

-----

1 point by akkartik 4731 days ago | link

Yeah sorry I didn't read your comment thoroughly.

-----

1 point by lark 4731 days ago | link

I tried having nginx stopped and only one Anarki running, and tests two and three do not work for me. Uploading a 7K file runs forever until the thread is killed (srv thread took too long).

-----

1 point by akkartik 4729 days ago | link

Ack, I just tried it with a 3MB file and the server lost connection.

Looks like the static multipart form hangs and times out while the fnid multipart form immediately disconnects. Is that what you see?

:(

-----

1 point by akkartik 4729 days ago | link

A 150k plaintext file works but a 147k binary pdf does not.

Update: The bug has to do with reading in bytes vs characters. Earlier, srv would readc from the POST body unless type was multipart, and your code (like the webupload example) would readb from the body otherwise. Now srv is always the one reading body, and it always reads characters using readc. As a result it gets confused by binary uploads that don't translate to characters.

Update 2: The sentence beginning 'Earlier' is incorrect, and webupload was always using readc as well. I'm not sure what I was looking at.

-----

1 point by akkartik 4729 days ago | link

  $ ls -l bintest
  -rw-r--r-- 1 akkartik akkartik 145974 Jun  5 12:39 bintest
  $ racket -f as.scm
  arc> (w/infile f "bintest" (len:readbytes 200000 f))
  145974
  arc> (w/infile f "bintest" (len:readchars 200000 f))
  141878
readchars does some interpretation but otherwise works fine. However when trying to upload bintest through a socket, it never terminates. Most curious.

Update: I've confirmed that the bytes in the file fail to be encoded as a unicode string, so presumably that's the issue. Another bit of sloppiness is that we're trying to read n characters from the request body where n is the Content-Length in bytes. webupload.arc has always had this problem.

-----

2 points by lark 4729 days ago | link

This seems consistent with me having to use readb rather than readc to get webupload.arc to work before.

-----

1 point by akkartik 4729 days ago | link

Ok, try it out after a git pull.

http://github.com/nex3/arc/commit/b3d97ffc91

Your existing code won't work as is. Since it's meaningless to try to convert possibly-binary data to a string, file contents are now returned as a list of bytes. There's a helper called bytes-string for when you're sure you have just ascii data. Otherwise you'll need to know the encoding of text uploads and convert the bytes appropriately.

I should warn you that it's gotten a lot slower. You might need to temporarily up threadlife. I have some ideas for speeding it up, but let's check first if this works for you.

-----

2 points by lark 4725 days ago | link

lib/form-tests.arc seems to work. It does take over a minute to upload a 415kb file over localhost.

I see the following error:

  Can't coerce  (98 98 83 116 88 110 82 115 98 103 . nil) sym
Should there be a working example in form-tests.arc that uses bytes-string?

-----

1 point by akkartik 4725 days ago | link

Ok, do a git pull for an example.

http://github.com/nex3/arc/commit/46e3820a6b

Can you give more detail on how you ran into that error? I'm sure there are still bugs.

-----

3 points by lark 4725 days ago | link

Here's a testcase:

  (mac usform (n s f . body)
   (w/uniq ga
     `(tag (form method 'post action fnurl* class (string ,s) id ,n name ,n
                enctype "multipart/form-data")
       (fnid-field (fnid (fn (,ga)
                           (prn)
                           (,f ,ga))))
       ,@body)))

  (defop || req
    (usform "this-is-a-bug" "" [ (pr "args are " _) ]
          (tab (row "price: " (input "price"))
               (submit))))

  (def main ()
     (asv))

-----

1 point by akkartik 4725 days ago | link

Ah, this is because the fnid field is being read as a list of bytes. I could convert fnid to string as a special case. Another option is to pass it in with the action url like in aform-multi: http://github.com/nex3/arc/blob/46e3820a6b/lib/srv.arc#L560

Update: Ok, I finally found a way to check when it's safe to convert to string, so now all fields (including fnid) will auto-convert to string when possible. If you get a list of bytes you know it has some sort of non-ascii data.

http://github.com/nex3/arc/commit/d5331ac897

But it's probably made things a tad slower still (let me know). Sucks that reading characters in scheme just hangs when it should throw an error.

-----

1 point by akkartik 4719 days ago | link

Eek, there was still a bug in that. Here's the corrected commit: http://github.com/nex3/arc/commit/1882b3b589

I've also made it faster; 4x faster in my experiments. http://github.com/nex3/arc/commit/16173ec1ff

Do a git pull and give it a whirl.

-----

1 point by akkartik 4731 days ago | link

That is really weird. I find myself momentarily out of ideas :( Maybe some sort of linux setting that controls how ports are opened? Are you running iptables or anything like that?

-----

1 point by lark 4729 days ago | link

Which version of racket are you using? I ran this with 5.2.1.

-----

1 point by akkartik 4729 days ago | link

5.0.2 on Ubuntu. Do you think that could be an issue?

-----

1 point by lark 4731 days ago | link

No iptables. This is indeed strange.

-----

1 point by lark 4737 days ago | link

If b does not break backward compatibility, I prefer b. Else c.

-----

1 point by akkartik 4736 days ago | link

Done. I came up with a way to get the best of both worlds. Multipart request args are now packaged in a table with all metadata, and with the actual body in key "contents". The arg helper is smart enough to deref "contents" in this table, so you can just say (arg req "file") to get its contents. To get at other fields, use the new function multipart-metadata.

http://github.com/nex3/arc/commit/72a6c69b38

-----

1 point by lark 4738 days ago | link | parent | on: Is there something wrong with @ in Anarki?

Escaping as '@@' worked, thanks.

-----


Thank you for the fix, that was fast!

I get in trouble when needing to update Anarki. Some patches like this one don't apply on the Anarki version I use and it seems only a brand new git clone gives the latest Anarki version. Which then requires I move around data, stuff in static, etc.

Is there a better way? How can I separate my app from the Anarki changes?

Can one run .arc programs from a directory that is different than the directory Anarki lives in?

-----

1 point by akkartik 4738 days ago | link

A failing test makes everything easier!

You can run anarki from anywhere:

  $ racket -f $ARC/as.scm
If you aren't making many changes to the base arc it might also make sense to stay updated with anarki. You just have to do a git pull every now and then. Keep your app in new files; that'll ensure pulls don't cause conflicts.

In the short term if you send me your srv.arc I'll make the change for you. (email in profile)

-----

1 point by lark 4738 days ago | link

Note that the latest Anarki reports the following after calling (asv):

  reference to undefined identifier: _ranked-stories*

-----

1 point by akkartik 4737 days ago | link

Yes, anarki loads news.arc by default. You probably don't want to do that in your repo. Delete the line from libs.arc. Feel free to do that in anarki as well if it'll make your life easier.

-----

1 point by lark 4736 days ago | link

It seems strange news.arc is included.

-----

1 point by akkartik 4736 days ago | link

Yes the original distribution doesn't load it by default. But I found that many people come to arc wanting to see how HN runs and it seemed worth reducing one step for them.

On a more pragmatic level, I found I was repeatedly making changes and forgetting to test them with news.arc. Loading it by default was at least a superficial sanity check. But this isn't a big deal. Like I said, feel free to delete the load, commit and git push.

-----


Has anyone managed to upload the file AND save the file to a file?

(readc req!in) seems to get stuck before reading the whole thing. Here's the source:

  (w/outfile o f
     (whilet c (and (> n 0) (readc req!in))
               (-- n)
               (pr "n now is " n)
               (disp c o)))

-----

2 points by rocketnia 4763 days ago | link

Are you uploading a text file encoded in UTF-8, as 'readc expects? It's probably waiting for the rest of a character.

If 'readb gives you issues too, then that's not it.

-----

1 point by lark 4761 days ago | link

readb gets stuck too.

Also, is there something like aform-multi that does not use fnids? I need a static upload url.

-----

2 points by lark 4760 days ago | link

This works at least:

  (mac form-multi (n . body)
    (w/uniq ga
      `(tag (form method 'post
                  enctype "multipart/form-data"
                  action ,n)
         ,@body)))

-----

2 points by lark 4760 days ago | link

Only 389120 bytes are read with a readb.

This is precisely 380 * 1024, which is suspicious.

-----

1 point by akkartik 4760 days ago | link

I can read files past the 380K limit. Here's me reading a 400K file.

  arc> (= i 0)
  arc> (w/infile in "x" (whilet c readb.in ++.i))
  arc> i
  400000
Does this work for you?

-----

1 point by lark 4760 days ago | link

This example works for me, but it's not an example that reads a file that is uploaded. It's an example that reads a file that is local.

Can you read the file that was POSTed and save it? Ignore parsing out the multipart stuff. Just save what came in through the request.

Here's the test at /upload_is_broken

  (mac form-multi (n . body)
    (w/uniq ga
      `(tag (form method 'post
                  enctype "multipart/form-data"
                  action ,n)
         ,@body)))

  (defop upload_is_broken req
    (form-multi "upload_static"                           
      (gentag input type 'file name 'name)
      (submit "upload")))

  (defop upload_static req
     (withs (n req!clen
               f (string "/dev/shm/" (uniq)))
            (pr "saving multipart data\n")
            (pr "clen is " n "\n")
            (w/outfile o f
                       (whilet c (and (> n 0) (readb req!in))
                               (-- n)
                               ;;(pr "n now is " n)                                                                         
                               (writeb c o)))
            (pr "SAVED multipart data. Success!!!\n")))
This does not work for me.

-----

1 point by akkartik 4760 days ago | link

It worked fine for me:

  saving multipart data clen is 1591333 SAVED multipart data. Success!!!
What's the specific file you're uploading?

-----

1 point by lark 4759 days ago | link

I misled you, I'm sorry. The example I just provided works for me.

http://tyche.pu-toyama.ac.jp/~a-urasim/lsvl/data/bzip2_1.0.5...

  $ md5sum bzip2_1.0.5.orig.tar.gz 
  3c15a0c8d1d3ee1c46a1634d00617b1a  bzip2_1.0.5.orig.tar.gz

  saving multipart data clen is 841607 SAVED multipart data. Success!!!
Yet the full app I have that uses this logic does not work. I'm not sure I can explain why.

-----

1 point by akkartik 4759 days ago | link

Thanks for the update. If you manage to narrow it down to a new code sample I'd love to see it.

-----

2 points by lark 4759 days ago | link

I verified that the example code I just provided does not work if nginx 0.7.67-3+squeeze2 from Debian is proxying connections to Anarki with the following configuration:

  server {
    listen 80;
    server_name  somewebsite.com;
    access_log /var/log/nginx/somewebsite.com.access.log;

    location / {
      proxy_pass        http://somewebsite.com:2012;
      proxy_set_header  X-Real-IP  $remote_addr;
    }
  }

-----

1 point by akkartik 4759 days ago | link

That's really useful, thanks. A quick google for 'nginx post length limit' brings up this link: http://www.rockia.com/2011/01/how-to-change-nginx-file-uploa... which suggests changing client_max_body_size. Does that help?

-----

1 point by lark 4758 days ago | link

Thanks for the link.

I tried setting the following in /etc/nginx/sites-available/somewebsite.com:

  server {
  # ... various vars as in http://arclanguage.org/item?id=16317 plus the following:
  client_max_body_size 10m;
  }
I also tried with client_max_body_size 10000000;

In both cases uploading the bzip2 file hangs.

I also tried setting client_max_body_size in /etc/nginx/nginx.conf but there get a different error:

  Restarting nginx: [emerg]: unknown directive "client_max_body_size" in /etc/nginx/nginx.conf:31
So it doesn't work for me. The documentation at http://nginx.org/en/docs/http/ngx_http_core_module.html#clie... suggests that the default value is 1m. This means that bzip2, which is under 1m, should be uploaded without a problem.

Update: Tried setting "client_max_body_size 32m;" under the "http" section in /etc/nginx/nginx.conf but posting still hangs.

-----

1 point by akkartik 4750 days ago | link

Ok I finally got around to trying to replicate this, and you're right, that setting doesn't seem to make a difference.

Sorry this took so long.

-----

1 point by akkartik 4758 days ago | link

I assume you restarted the nginx service?

-----

1 point by lark 4757 days ago | link

Yes. Does upload in Anarki behind nginx work for you?

-----


Thanks a lot guys!

-----

2 points by lark 4776 days ago | link | parent | on: A few questions about Arc

You can always call Python from Arc to use some libraries.

A Python dict to s-exp converter is about 38 lines. There's a fromjson.arc (breaks over some input) and a tojson.arc (broken, creates an extra }) somewhere that could help talk to web services.

-----


Makes sense. Here's the issue: how do I save the multipart data of an file upload to a file quickly? Is there something more efficient than this:

  (w/outfile o f
    (whilet c (and (> n 0) (readc req!in))
              (-- n)
              (disp c o)))
This is derived from: http://github.com/nex3/arc/blob/master/lib/webupload.arc

Using a:

              (writec c o)))
produces the same effect.

-----

2 points by rocketnia 4787 days ago | link

I found some cool stuff at (http://docs.racket-lang.org/reference/port-lib.html#(def._((...).

This might work:

  (w/outfile o f
    (let i ($.make-limited-input-port req!in n)
      (after ($.copy-port i o)
        close.i)))
For all I know, closing i may not be necessary:

  (w/outfile o f
    ($.copy-port ($.make-limited-input-port req!in n) o))
Note that this copies n bytes. The code you posted deals with n characters for some reason, even though Arc provides 'readb and 'writeb for dealing with bytes.

-----

1 point by lark 4787 days ago | link

Thanks for the help. I tried with readb instead of readc and received a browser error with the 874996-byte file.

-----

1 point by lark 4787 days ago | link

It seems saving w/outfile saves the file correctly as sent. It's just that Anarki does not return after that.

Also, uploading a 874996-byte file results into only 183045 of those bytes being available in the multipart data that end up being saved, and the browser reports an error:

  The webpage at http://lovelywebsite.com/x?fnid=6bl1DEG5yq
  might be temporarily down or it may have moved permanently
  to a new web address.
Also, when this error uploading a 874996-byte file occurs, the 'srv thread took too long' error message is not displayed at all: the browser error occurs within 1-2 secs.

-----

2 points by rocketnia 4787 days ago | link

That sounds almost like you're coming across a request size limit somewhere in your server (maybe in news.arc or app.arc or srv.arc, maybe in Apache or nginx or whatever)... but probably not since the upload is less than 4MB. All I know is PHP tends to limit uploads to 4MB unless you reconfigure it. :-p

Maybe you're coming across an issue with the fact that bytes are being treated as characters? Do you have another file you could test? (Maybe one you could share with us?)

-----

1 point by lark 4787 days ago | link

I thought there might be a request size limit, since there's an nginx in front of Anarki. But then I tried connecting directly to the Anarki web port and got the same result.

Here's a 822K file which I just confirmed fails to be uploaded:

http://tyche.pu-toyama.ac.jp/~a-urasim/lsvl/data/bzip2_1.0.5...

Can anyone get this to upload with webupload.arc successfully?

-----

1 point by rocketnia 4782 days ago | link

Sorry for leaving you hanging here.... I'm not really in the practice of running news.arc, and when I asked for a file to use for testing it's because I thought maybe someone else would pick up my slack. XD

-----

1 point by lark 4788 days ago | link | parent | on: Save-table in Anarki: is it different?

This change in Anarki breaks backward compatibility with Arc.

Is this a goal of Anarki?

-----

1 point by akkartik 4788 days ago | link

http://www.arclanguage.org says "Arc is fluid and future releases are guaranteed to break all your code." As a result the community tends not to care about compatibility either. Anarki has numerous little incompatibilities. Since literally anybody can commit to it at any time it's hard to make any assumptions about it whatsoever.

All of us choose to live in one repo; either arc3.1 or anarki or something of our own. My personal set of favorite incompatibilities is at http://github.com/akkartik/arc, for example. My recommendation: jumping back and forth between arc3.1 and anarki is more trouble than it's worth.

I had to gradually accustom myself to how things work here. Even now I monitor new commits to anarki as I pull them. It can't be like a library you blindly rely on.

-----

2 points by lark 4788 days ago | link

That's a fair response. Thank you for the help and the clarification.

-----

1 point by akkartik 4788 days ago | link

You're welcome! One of the great benefits of this model is that it is literally frictionless to propose new ideas. I hope you will feel free to make your own edits directly to anarki. I'd love to see you post about them here if the rationale isn't obvious, but it's always ok to make changes first and see if anybody complains :)

For example, a while ago I decided that using + for both addition and concatenation was ugly (http://github.com/nex3/arc/commit/49005e3d60). But then a couple of people complained and I reverted (http://github.com/nex3/arc/commit/bd42b93742). We're a small group, so edit wars haven't been a problem so far.

-----

1 point by lark 4788 days ago | link | parent | on: Save-table in Anarki: is it different?

Is there a stable Anarki I could use in the meantime?

-----

1 point by lark 4788 days ago | link | parent | on: Save-table in Anarki: is it different?

This might explain it.

  lib/math.arc:390:(def beta (z w)

-----

1 point by lark 4788 days ago | link

Nope, that's not it. A different deftem name still causes this error.

-----

1 point by akkartik 4788 days ago | link

It's probably my change for http://arclanguage.org/item?id=15664 again, just like http://arclanguage.org/item?id=16020. Let me take a look. Can you provide simple failing example?

Update 1: As part of that change I changed how we represent templates. In arc 3.1:

  arc> (deftem foo field1 34)
  arc> inst!foo
  #hash((field1 . 34))
vs in anarki:

  arc> (deftem foo field1 34)
  arc> inst!foo
  #(tagged tem (foo #hash() #hash() . nil))
This makes serialization of templates more reliable, but now templates aren't hash-tables anymore; instead of (maptable ... x) you have to say (maptable ... rep.x).

Does this sound like some code you wrote? I'm looking for any places in anarki that use table functions on templates.

Update 2: I'd forgotten to update blog.arc; that's now fixed (http://github.com/nex3/arc/commit/2bd80ecb65). But I don't think this fixes it for you.

-----

1 point by lark 4788 days ago | link

  (deftem bbb
   code nil)
  (withs (b (inst 'bbb 'code "3"))
         (save-table b (string "/dev/shm/" b!code)))

-----

1 point by lark 4788 days ago | link

temstore worked.

This change in Anarki breaks backward compatibility with Arc. news.arc for example doesn't work after this change.

-----

1 point by akkartik 4788 days ago | link

Great; sorry about that.

I just doublechecked news.arc and didn't see an issue. Can you be more specific? Note that you can't mix news.arc from arc3.1 with arc.arc from anarki because of this incompatible change.

-----

1 point by lark 4788 days ago | link

The issue is that everywhere that one was calling save-table now one needs to replace save-table with temstore.

One needs to modify the application so that saving works again.

-----

1 point by akkartik 4788 days ago | link

That is so, yes. Since arc can change at any time, to use it you have to be open to changing your app anytime you pull in updates. It's one of the reasons arc is small; it has no bloat from historical baggage. I've given up and even keep my own code directly in the arc directory.

I'm curious what your current setup is. Are you running off of anarki? Or copying parts of it over to your own repo?

-----

1 point by lark 4788 days ago | link

I'd rather not fork my own copy of Arc.

All I want is to be able to upload a file. Arc can't do it, Anarki can. Arc can change at any time, but Arc did not change in a long time.

I also noticed the following since switching the app to Anarki:

  procedure ...nk/anarki/ac.scm:972:33: expects 1 argument, given 0

-----

1 point by rocketnia 4787 days ago | link

I just looked in Arc 3.1, in all of Anarki's branches, a few commits back in Anarki's master ac.scm, and I didn't find anything at line 972 that would cause an error like that.

I did notice that some functions that are supposed to expect 1 argument in news.arc currently expect 0, so I fixed that: https://github.com/nex3/arc/commit/f311b3879c15a27518bbe0fad...

I don't know where to start testing news.arc, so please speak up if I've made things even worse.

-----

2 points by rocketnia 4787 days ago | link

Looks like I came in just after akkartik noticed the same thing, and I just fixed some overlooked places. XD

-----

1 point by akkartik 4787 days ago | link

I think I tracked this down. Can you pull from github?

-----

1 point by akkartik 4788 days ago | link

I'm still curious if you were seeing an issue in news.arc on anarki outside of your own code. If so I really should fix it, but I don't see anything wrong so far. When I made the change I tried to be careful and replace save-table with temstore: http://github.com/nex3/arc/commit/c125d0330c.

-----

1 point by akkartik 4788 days ago | link

Instead of (save-table ...) say (temstore bbb ...).

If you copied this way of doing things from somewhere, let me know and I'll try to update it.

-----

More