[tor-commits] [onionoo/master] Improve (de-)serialization for the fields parameter.

karsten at torproject.org karsten at torproject.org
Tue Apr 28 13:11:59 UTC 2020


commit 636a5861fd84e2d2b63e3afb59285fe059295e28
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Fri Apr 3 08:40:49 2020 +0200

    Improve (de-)serialization for the fields parameter.
    
    Implements #17939.
---
 .../metrics/onionoo/server/ResponseBuilder.java    | 216 +++------------------
 1 file changed, 23 insertions(+), 193 deletions(-)

diff --git a/src/main/java/org/torproject/metrics/onionoo/server/ResponseBuilder.java b/src/main/java/org/torproject/metrics/onionoo/server/ResponseBuilder.java
index f6453ae..33508db 100644
--- a/src/main/java/org/torproject/metrics/onionoo/server/ResponseBuilder.java
+++ b/src/main/java/org/torproject/metrics/onionoo/server/ResponseBuilder.java
@@ -11,17 +11,19 @@ import org.torproject.metrics.onionoo.docs.DocumentStoreFactory;
 import org.torproject.metrics.onionoo.docs.SummaryDocument;
 import org.torproject.metrics.onionoo.docs.UptimeDocument;
 import org.torproject.metrics.onionoo.docs.WeightsDocument;
-import org.torproject.metrics.onionoo.util.FormattingUtils;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Properties;
 
@@ -105,11 +107,10 @@ public class ResponseBuilder {
     this.bridgesTruncated = bridgesTruncated;
   }
 
-  private String[] fields;
+  private List<String> fields;
 
   public void setFields(String[] fields) {
-    this.fields = new String[fields.length];
-    System.arraycopy(fields, 0, this.fields, 0, fields.length);
+    this.fields = Arrays.asList(fields);
   }
 
   public void buildResponse(PrintWriter pw) {
@@ -234,198 +235,27 @@ public class ResponseBuilder {
 
   private String writeDetailsLines(SummaryDocument entry) {
     String fingerprint = entry.getFingerprint();
-    if (this.fields != null) {
-      /* TODO Maybe there's a more elegant way (more maintainable, more
-       * efficient, etc.) to implement this? */
-      DetailsDocument detailsDocument = documentStore.retrieve(
-          DetailsDocument.class, true, fingerprint);
-      if (detailsDocument != null) {
-        DetailsDocument dd = new DetailsDocument();
-        for (String field : this.fields) {
-          switch (field) {
-            case "nickname":
-              dd.setNickname(detailsDocument.getNickname());
-              break;
-            case "fingerprint":
-              dd.setFingerprint(detailsDocument.getFingerprint());
-              break;
-            case "hashed_fingerprint":
-              dd.setHashedFingerprint(
-                  detailsDocument.getHashedFingerprint());
-              break;
-            case "or_addresses":
-              dd.setOrAddresses(detailsDocument.getOrAddresses());
-              break;
-            case "exit_addresses":
-              dd.setExitAddresses(detailsDocument.getExitAddresses());
-              break;
-            case "dir_address":
-              dd.setDirAddress(detailsDocument.getDirAddress());
-              break;
-            case "last_seen":
-              dd.setLastSeen(detailsDocument.getLastSeen());
-              break;
-            case "last_changed_address_or_port":
-              dd.setLastChangedAddressOrPort(
-                  detailsDocument.getLastChangedAddressOrPort());
-              break;
-            case "first_seen":
-              dd.setFirstSeen(detailsDocument.getFirstSeen());
-              break;
-            case "running":
-              dd.setRunning(detailsDocument.isRunning());
-              break;
-            case "flags":
-              dd.setFlags(detailsDocument.getFlags());
-              break;
-            case "country":
-              dd.setCountry(detailsDocument.getCountry());
-              break;
-            case "country_name":
-              dd.setCountryName(detailsDocument.getCountryName());
-              break;
-            case "region_name":
-              dd.setRegionName(detailsDocument.getRegionName());
-              break;
-            case "city_name":
-              dd.setCityName(detailsDocument.getCityName());
-              break;
-            case "latitude":
-              dd.setLatitude(detailsDocument.getLatitude());
-              break;
-            case "longitude":
-              dd.setLongitude(detailsDocument.getLongitude());
-              break;
-            case "as":
-              dd.setAs(detailsDocument.getAs());
-              break;
-            case "as_name":
-              dd.setAsName(detailsDocument.getAsName());
-              break;
-            case "consensus_weight":
-              dd.setConsensusWeight(detailsDocument.getConsensusWeight());
-              break;
-            case "verified_host_names":
-              dd.setVerifiedHostNames(detailsDocument.getVerifiedHostNames());
-              break;
-            case "unverified_host_names":
-              dd.setUnverifiedHostNames(
-                  detailsDocument.getUnverifiedHostNames());
-              break;
-            case "last_restarted":
-              dd.setLastRestarted(detailsDocument.getLastRestarted());
-              break;
-            case "bandwidth_rate":
-              dd.setBandwidthRate(detailsDocument.getBandwidthRate());
-              break;
-            case "bandwidth_burst":
-              dd.setBandwidthBurst(detailsDocument.getBandwidthBurst());
-              break;
-            case "observed_bandwidth":
-              dd.setObservedBandwidth(
-                  detailsDocument.getObservedBandwidth());
-              break;
-            case "advertised_bandwidth":
-              dd.setAdvertisedBandwidth(
-                  detailsDocument.getAdvertisedBandwidth());
-              break;
-            case "exit_policy":
-              dd.setExitPolicy(detailsDocument.getExitPolicy());
-              break;
-            case "exit_policy_summary":
-              dd.setExitPolicySummary(
-                  detailsDocument.getExitPolicySummary());
-              break;
-            case "exit_policy_v6_summary":
-              dd.setExitPolicyV6Summary(
-                  detailsDocument.getExitPolicyV6Summary());
-              break;
-            case "contact":
-              dd.setContact(detailsDocument.getContact());
-              break;
-            case "platform":
-              dd.setPlatform(detailsDocument.getPlatform());
-              break;
-            case "consensus_weight_fraction":
-              dd.setConsensusWeightFraction(
-                  detailsDocument.getConsensusWeightFraction());
-              break;
-            case "guard_probability":
-              dd.setGuardProbability(detailsDocument.getGuardProbability());
-              break;
-            case "middle_probability":
-              dd.setMiddleProbability(
-                  detailsDocument.getMiddleProbability());
-              break;
-            case "exit_probability":
-              dd.setExitProbability(detailsDocument.getExitProbability());
-              break;
-            case "recommended_version":
-              dd.setRecommendedVersion(
-                  detailsDocument.isRecommendedVersion());
-              break;
-            case "hibernating":
-              dd.setHibernating(detailsDocument.isHibernating());
-              break;
-            case "transports":
-              dd.setTransports(detailsDocument.getTransports());
-              break;
-            case "effective_family":
-              dd.setEffectiveFamily(detailsDocument.getEffectiveFamily());
-              break;
-            case "measured":
-              dd.setMeasured(detailsDocument.isMeasured());
-              break;
-            case "alleged_family":
-              dd.setAllegedFamily(detailsDocument.getAllegedFamily());
-              break;
-            case "indirect_family":
-              dd.setIndirectFamily(detailsDocument.getIndirectFamily());
-              break;
-            case "unreachable_or_addresses":
-              dd.setUnreachableOrAddresses(
-                  detailsDocument.getUnreachableOrAddresses());
-              break;
-            case "version":
-              dd.setVersion(detailsDocument.getVersion());
-              break;
-            case "version_status":
-              dd.setVersionStatus(detailsDocument.getVersionStatus());
-              break;
-            case "bridgedb_distributor":
-              dd.setBridgedbDistributor(
-                  detailsDocument.getBridgedbDistributor());
-              break;
-            default:
-              /* Not a field that we know of. Ignore. */
-              break;
-          }
-        }
-        /* Whenever we provide Jackson with a string containing an escaped
-         * non-ASCII character like \u00F2, it escapes the \ to \\, which
-         * we need to undo before including the string in a response. */
+    DetailsDocument detailsDocument = documentStore.retrieve(
+        DetailsDocument.class, false, fingerprint);
+    String documentString = "";
+    if (null != detailsDocument) {
+      documentString = detailsDocument.getDocumentString();
+      if (null != this.fields) {
         try {
-          return FormattingUtils.replaceValidUtf(
-              objectMapper.writeValueAsString(dd));
-        } catch (JsonProcessingException e) {
-          return "";
+          LinkedHashMap<String, Object> parsedDocument
+              = objectMapper.readValue(documentString,
+              new TypeReference<LinkedHashMap<String, Object>>() {});
+          parsedDocument.keySet().retainAll(this.fields);
+          documentString = objectMapper.writeValueAsString(parsedDocument);
+        } catch (IOException e) {
+          /* Handle below. */
+          documentString = "";
         }
-      } else {
-        // TODO We should probably log that we didn't find a details
-        // document that we expected to exist.
-        return "";
-      }
-    } else {
-      DetailsDocument detailsDocument = documentStore.retrieve(
-          DetailsDocument.class, false, fingerprint);
-      if (detailsDocument != null) {
-        return detailsDocument.getDocumentString();
-      } else {
-        // TODO We should probably log that we didn't find a details
-        // document that we expected to exist.
-        return "";
       }
     }
+    // TODO We should probably log that we didn't find a details
+    // document that we expected to exist.
+    return documentString;
   }
 
   private String writeBandwidthLines(SummaryDocument entry) {



More information about the tor-commits mailing list