This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-05
Channels
- # adventofcode (111)
- # announcements (20)
- # babashka (19)
- # beginners (47)
- # calva (7)
- # clojure (56)
- # clojure-dev (27)
- # clojurescript (2)
- # events (1)
- # holy-lambda (1)
- # juxt (2)
- # meander (18)
- # minecraft (4)
- # missionary (107)
- # nextjournal (21)
- # off-topic (30)
- # reagent (7)
- # reitit (19)
- # releases (1)
- # tools-build (8)
- # tools-deps (7)
- # vim (22)
- # xtdb (4)
I need to create an anonymous function that returns the or
of two other predicates on a single input. I've come up with two ways to represent this, and they do both work, but I suspect there's a simpler representation I can't find. Any thoughts?
#(or (pred1 %) (pred2 %))
#(some (fn [pred] (pred %)) [pred1 pred2])
Of course it's that simple! Thanks, @U04V4KLKC!
(some-fn pred1 pred2)
Hi, how would you call this in Clojure?
Storage.SignUrlOption.httpMethod(HttpMethod.PUT)
from:
https://github.com/googleapis/java-storage/blob/main/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java#L64
Thank youThis is the java example
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.HttpMethod;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageException;
import com.google.cloud.storage.StorageOptions;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class GenerateV4PutObjectSignedUrl {
/**
* Signing a URL requires Credentials which implement ServiceAccountSigner. These can be set
* explicitly using the Storage.SignUrlOption.signWith(ServiceAccountSigner) option. If you don't,
* you could also pass a service account signer to StorageOptions, i.e.
* StorageOptions().newBuilder().setCredentials(ServiceAccountSignerCredentials). In this example,
* neither of these options are used, which means the following code only works when the
* credentials are defined via the environment variable GOOGLE_APPLICATION_CREDENTIALS, and those
* credentials are authorized to sign a URL. See the documentation for Storage.signUrl for more
* details.
*/
public static void generateV4GPutObjectSignedUrl(
String projectId, String bucketName, String objectName) throws StorageException {
// String projectId = "my-project-id";
// String bucketName = "my-bucket";
// String objectName = "my-object";
Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
// Define Resource
BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, objectName)).build();
// Generate Signed URL
Map<String, String> extensionHeaders = new HashMap<>();
extensionHeaders.put("Content-Type", "application/octet-stream");
URL url =
storage.signUrl(
blobInfo,
15,
TimeUnit.MINUTES,
Storage.SignUrlOption.httpMethod(HttpMethod.PUT),
Storage.SignUrlOption.withExtHeaders(extensionHeaders),
Storage.SignUrlOption.withV4Signature());
System.out.println("Generated PUT signed URL:");
System.out.println(url);
System.out.println("You can use this URL with any user agent, for example:");
System.out.println(
"curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file '"
+ url
+ "'");
}
}
I am fighting with the url part You can see my last try..
(defn generate-v4-gput-object-signed-url [project-id bucket-name object-name]
(let [storage (-> (StorageOptions/newBuilder) (.setProjectId project-id).build .getService)
blob-info (-> (BlobInfo/newBuilder
(BlobId/of bucket-name object-name))
.build)
extension-headers (-> (HashMap.)
(.put "Content-Type" "application/octet-stream"))
url ((.signUrl storage blob-info 15 (TimeUnit/MINUTES)
;; doesn't work
(.httpMethod com.google.cloud.storage.Storage$SignUrlOption (HttpMethod/PUT))
(.withExtHeaders com.google.cloud.storage.Storage$SignUrlOption extension-headers)
(.withV4Signature com.google.cloud.storage.Storage$SignUrlOption)))]
(println "Generated PUT signed URL:")
(println url)
(println "You can use this URL with any user agent, for example:")
(println (str "curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file '"
url
"'"))))
The sign url option class is package private, so the expectation is you don't interact with it directly, so I would find some java examples of using the library
Hmph, this is coming from gcp site https://cloud.google.com/storage/docs/samples/storage-generate-upload-signed-url-v4#storage_generate_upload_signed_url_v4-java
But I am not entirely sure the clojure compiler will be happy about a package private class with a public static method
https://clojure.org/reference/java_interop#_member_access has examples of what static method calls look like
You have the class name correct, but are trying to invoke a method named httpMethod on the Class object
You also have an extra set of parens where you at invoking the result of signUrl as a function
My biggest problem is how to call static function on nested class…. I though that by Storage$SignUrlOption I should be able to access the inner class and then I call its static function
Possibly, but the code you shared is broken, and not calling a static method at all, and you haven't shared details of the error messages you got, so I cannot assess if you had a syntax or there was some other problem
It sounds to me like maybe you weren't calling the static method correctly (the way you are describing it, accessing the inner class then calling static methods on it, doesn't in my mind match the syntax of calling a static method)
The syntax is just (theclassname/themethodname arg1 arg2 etc)
so (Storage$SignUrlOptiom/httpMethod HttpMethod/PUT)
If you did have the syntax of the static method call correct, the error you are hitting might just be the varargs not being correct, but I dunno what error you got
Now I am getting varargs error, finally 🙂 This is the first time i have needed to call a class inside interface
Clojure's java interop would be better named jvm interop, because every place java and the jvm differ, clojure exposes the jvms version
Would you recommend some text about details maybe? The clojure <-> java and especially clojure <-> other jvm languages interop is not my strong skill
Inner classes aren't a jvm thing, they are just normal class files, with names created by concatenating the enclosing class and the inner classes name separated by a $
Varargs don't exist on the jvm, they just methods that take a trailing array argument
Good info.. This is the updated and working 1:1 code if anybody is interested…
(defn generate-v4-gput-object-signed-url [project-id bucket-name object-name]
(let [storage (-> (StorageOptions/newBuilder) (.setProjectId project-id) .build .getService)
blob-info (-> (BlobInfo/newBuilder
(BlobId/of bucket-name object-name))
.build)
extension-headers (doto (HashMap.)
(.put "Content-Type" "application/octet-stream"))
url (.signUrl storage blob-info 15 (TimeUnit/MINUTES)
(into-array [(com.google.cloud.storage.Storage$SignUrlOption/httpMethod HttpMethod/PUT)
(com.google.cloud.storage.Storage$SignUrlOption/withExtHeaders extension-headers)
(com.google.cloud.storage.Storage$SignUrlOption/withV4Signature)]))]
(println "Generated PUT signed URL:")
(println url)
(println "You can use this URL with any user agent, for example:")
(println (str "curl -X PUT -H 'Content-Type: application/octet-stream' --upload-file my-file '"
url
"'"))))
good job
I guess making requests with http-kit for example doesn't already do retry logic e.g. when 429 or whatever it is is returned?
Http-kit does not do range-queries unfortunately
(unrelated but something else that it could use)
492... "too many requests" ... what behavior do you want? long-poll retry?
https://developer.atlassian.com/cloud/jira/platform/rate-limiting/ I was reading this. Incremental backof I guess. Don't know about long polling
courier is a thing that'll handle a lot of interesting http client use cases https://github.com/cjohansen/courier
things like retries, caching, inter-request dependencies