Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: third_party/WebKit/Source/platform/network/HTTPParsers.cpp

Issue 2889033002: Better header value parsing for Server-Timing. (Closed)
Patch Set: test escaped double-quotes Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 2 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
3 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ 4 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
5 * Copyright (C) 2009 Google Inc. All rights reserved. 5 * Copyright (C) 2009 Google Inc. All rights reserved.
6 * Copyright (C) 2011 Apple Inc. All Rights Reserved. 6 * Copyright (C) 2011 Apple Inc. All Rights Reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 842
843 bool ParseContentRangeHeaderFor206(const String& content_range, 843 bool ParseContentRangeHeaderFor206(const String& content_range,
844 int64_t* first_byte_position, 844 int64_t* first_byte_position,
845 int64_t* last_byte_position, 845 int64_t* last_byte_position,
846 int64_t* instance_length) { 846 int64_t* instance_length) {
847 return net::HttpUtil::ParseContentRangeHeaderFor206( 847 return net::HttpUtil::ParseContentRangeHeaderFor206(
848 StringUTF8Adaptor(content_range).AsStringPiece(), first_byte_position, 848 StringUTF8Adaptor(content_range).AsStringPiece(), first_byte_position,
849 last_byte_position, instance_length); 849 last_byte_position, instance_length);
850 } 850 }
851 851
852 template <typename CharType>
853 inline bool IsNotServerTimingHeaderDelimiter(CharType c) {
854 return c != '=' && c != ';' && c != ',';
855 }
856
857 const LChar* ParseServerTimingToken(const LChar* begin,
858 const LChar* end,
859 String& result) {
860 const LChar* position = begin;
861 skipWhile<LChar, IsNotServerTimingHeaderDelimiter>(position, end);
862 result = String(begin, position - begin).StripWhiteSpace();
863 return position;
864 }
865
866 String CheckDoubleQuotedString(const String& value) {
867 if (value.length() < 2 || value[0] != '"' ||
868 value[value.length() - 1] != '"') {
869 return value;
870 }
871
872 StringBuilder out;
873 unsigned pos = 1; // Begin after the opening DQUOTE.
874 unsigned len = value.length() - 1; // End before the closing DQUOTE.
875
876 // Skip past backslashes, but include everything else.
877 while (pos < len) {
878 if (value[pos] == '\\')
879 pos++;
880 if (pos < len)
881 out.Append(value[pos++]);
882 }
883
884 return out.ToString();
885 }
886
887 std::unique_ptr<ServerTimingHeaderVector> ParseServerTimingHeader( 852 std::unique_ptr<ServerTimingHeaderVector> ParseServerTimingHeader(
888 const String& headerValue) { 853 const String& headerValue) {
889 std::unique_ptr<ServerTimingHeaderVector> headers = 854 std::unique_ptr<ServerTimingHeaderVector> headers =
890 WTF::MakeUnique<ServerTimingHeaderVector>(); 855 WTF::MakeUnique<ServerTimingHeaderVector>();
891 856
892 if (!headerValue.IsNull()) { 857 if (!headerValue.IsNull()) {
893 DCHECK(headerValue.Is8Bit()); 858 DCHECK(headerValue.Is8Bit());
894 859
895 const LChar* position = headerValue.Characters8(); 860 unsigned index = 0;
e_hakkinen 2017/05/24 11:48:17 Please rebase, create a HeaderFieldTokenizer objec
896 const LChar* end = position + headerValue.length(); 861 while (index < headerValue.length()) {
897 while (position < end) { 862 StringView metric;
898 String metric, value, description = ""; 863 if (!ConsumeToken(Mode::kNormal, headerValue, index, metric)) {
899 position = ParseServerTimingToken(position, end, metric); 864 break;
900 if (position != end && *position == '=') {
901 position = ParseServerTimingToken(position + 1, end, value);
902 } 865 }
903 if (position != end && *position == ';') { 866
904 position = ParseServerTimingToken(position + 1, end, description); 867 StringView duration;
868 String description;
869 if (Consume('=', headerValue, index)) {
870 ConsumeToken(Mode::kNormal, headerValue, index, duration);
905 } 871 }
906 position++; 872 if (Consume(';', headerValue, index)) {
873 ConsumeTokenOrQuotedString(Mode::kNormal, headerValue, index,
874 description);
875 }
907 876
908 headers->push_back(WTF::MakeUnique<ServerTimingHeader>( 877 headers->push_back(WTF::MakeUnique<ServerTimingHeader>(
909 metric, value.ToDouble(), CheckDoubleQuotedString(description))); 878 metric.ToString(), duration.ToString().ToDouble(),
879 description ? description : ""));
880
881 if (!Consume(',', headerValue, index)) {
882 break;
883 }
910 } 884 }
911 } 885 }
912 return headers; 886 return headers;
913 } 887 }
914 888
915 bool IsTokenCharacter(Mode mode, UChar c) { 889 bool IsTokenCharacter(Mode mode, UChar c) {
916 if (c >= 128) 890 if (c >= 128)
917 return false; 891 return false;
918 if (c < 0x20) 892 if (c < 0x20)
919 return false; 893 return false;
(...skipping 17 matching lines...) Expand all
937 case '?': 911 case '?':
938 case '=': 912 case '=':
939 return mode == Mode::kRelaxed; 913 return mode == Mode::kRelaxed;
940 default: 914 default:
941 return true; 915 return true;
942 } 916 }
943 } 917 }
944 918
945 bool Consume(char c, const String& input, unsigned& index) { 919 bool Consume(char c, const String& input, unsigned& index) {
946 DCHECK_NE(c, ' '); 920 DCHECK_NE(c, ' ');
921 // TODO: skip all whitespace, not just spaces
Yoav Weiss 2017/05/22 08:21:33 Can you `TODO(cvazac):` this? (and maybe open an i
e_hakkinen 2017/05/24 11:48:17 Feel free to move these comments to HeaderFieldTok
922 // (https://tools.ietf.org/html/rfc7231#section-3.1.1)
947 while (index < input.length() && input[index] == ' ') 923 while (index < input.length() && input[index] == ' ')
948 ++index; 924 ++index;
949 925
950 if (index < input.length() && input[index] == c) { 926 if (index < input.length() && input[index] == c) {
951 ++index; 927 ++index;
952 return true; 928 return true;
953 } 929 }
954 return false; 930 return false;
955 } 931 }
956 932
957 bool ConsumeToken(Mode mode, 933 bool ConsumeToken(Mode mode,
958 const String& input, 934 const String& input,
959 unsigned& index, 935 unsigned& index,
960 StringView& output) { 936 StringView& output) {
961 DCHECK(output.IsNull()); 937 DCHECK(output.IsNull());
962 938
939 // TODO: skip all whitespace, not just spaces
963 while (index < input.length() && input[index] == ' ') 940 while (index < input.length() && input[index] == ' ')
964 ++index; 941 ++index;
965 942
966 auto start = index; 943 auto start = index;
967 while (index < input.length() && IsTokenCharacter(mode, input[index])) 944 while (index < input.length() && IsTokenCharacter(mode, input[index]))
968 ++index; 945 ++index;
969 946
970 if (start == index) 947 if (start == index)
971 return false; 948 return false;
972 949
(...skipping 22 matching lines...) Expand all
995 builder.Append(input[index]); 972 builder.Append(input[index]);
996 ++index; 973 ++index;
997 } 974 }
998 return false; 975 return false;
999 } 976 }
1000 977
1001 bool ConsumeTokenOrQuotedString(Mode mode, 978 bool ConsumeTokenOrQuotedString(Mode mode,
1002 const String& input, 979 const String& input,
1003 unsigned& index, 980 unsigned& index,
1004 String& output) { 981 String& output) {
982 // TODO: skip all whitespace, not just spaces
1005 while (index < input.length() && input[index] == ' ') 983 while (index < input.length() && input[index] == ' ')
1006 ++index; 984 ++index;
1007 if (input.length() == index) 985 if (input.length() == index)
1008 return false; 986 return false;
1009 if (input[index] == '"') { 987 if (input[index] == '"') {
1010 return ConsumeQuotedString(input, index, output); 988 return ConsumeQuotedString(input, index, output);
1011 } 989 }
1012 StringView view; 990 StringView view;
1013 auto result = ConsumeToken(mode, input, index, view); 991 auto result = ConsumeToken(mode, input, index, view);
1014 output = view.ToString(); 992 output = view.ToString();
1015 return result; 993 return result;
1016 } 994 }
1017 995
1018 bool IsEnd(const String& input, unsigned index) { 996 bool IsEnd(const String& input, unsigned index) {
1019 while (index < input.length()) { 997 while (index < input.length()) {
998 // TODO: skip all whitespace, not just spaces
1020 if (input[index] != ' ') 999 if (input[index] != ' ')
1021 return false; 1000 return false;
1022 ++index; 1001 ++index;
1023 } 1002 }
1024 return true; 1003 return true;
1025 } 1004 }
1026 1005
1027 } // namespace blink 1006 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698