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

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

Issue 229053004: Allow cache reuse of some requests with Cache-Control headers (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « Source/platform/network/HTTPParsers.h ('k') | Source/platform/network/HTTPParsersTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 16 matching lines...) Expand all
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33 #include "config.h" 33 #include "config.h"
34 #include "platform/network/HTTPParsers.h" 34 #include "platform/network/HTTPParsers.h"
35 35
36 #include "wtf/DateMath.h" 36 #include "wtf/DateMath.h"
37 #include "wtf/MathExtras.h"
37 #include "wtf/text/CString.h" 38 #include "wtf/text/CString.h"
38 #include "wtf/text/StringBuilder.h" 39 #include "wtf/text/StringBuilder.h"
39 #include "wtf/text/WTFString.h" 40 #include "wtf/text/WTFString.h"
40 #include "wtf/unicode/CharacterNames.h" 41 #include "wtf/unicode/CharacterNames.h"
41 42
42 using namespace WTF; 43 using namespace WTF;
43 44
44 namespace WebCore { 45 namespace WebCore {
45 46
46 // true if there is more to parse, after incrementing pos past whitespace. 47 // true if there is more to parse, after incrementing pos past whitespace.
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 } 678 }
678 679
679 size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned cha r>& body) 680 size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned cha r>& body)
680 { 681 {
681 body.clear(); 682 body.clear();
682 body.append(data, length); 683 body.append(data, length);
683 684
684 return length; 685 return length;
685 } 686 }
686 687
688 static bool isCacheHeaderSeparator(UChar c)
689 {
690 // See RFC 2616, Section 2.2
691 switch (c) {
692 case '(':
693 case ')':
694 case '<':
695 case '>':
696 case '@':
697 case ',':
698 case ';':
699 case ':':
700 case '\\':
701 case '"':
702 case '/':
703 case '[':
704 case ']':
705 case '?':
706 case '=':
707 case '{':
708 case '}':
709 case ' ':
710 case '\t':
711 return true;
712 default:
713 return false;
714 }
687 } 715 }
716
717 static bool isControlCharacter(UChar c)
718 {
719 return c < ' ' || c == 127;
720 }
721
722 static inline String trimToNextSeparator(const String& str)
723 {
724 return str.substring(0, str.find(isCacheHeaderSeparator));
725 }
726
727 static void parseCacheHeader(const String& header, Vector<pair<String, String> > & result)
728 {
729 const String safeHeader = header.removeCharacters(isControlCharacter);
730 unsigned max = safeHeader.length();
731 for (unsigned pos = 0; pos < max; /* pos incremented in loop */) {
732 size_t nextCommaPosition = safeHeader.find(',', pos);
733 size_t nextEqualSignPosition = safeHeader.find('=', pos);
734 if (nextEqualSignPosition != kNotFound && (nextEqualSignPosition < nextC ommaPosition || nextCommaPosition == kNotFound)) {
735 // Get directive name, parse right hand side of equal sign, then add to map
736 String directive = trimToNextSeparator(safeHeader.substring(pos, nex tEqualSignPosition - pos).stripWhiteSpace());
737 pos += nextEqualSignPosition - pos + 1;
738
739 String value = safeHeader.substring(pos, max - pos).stripWhiteSpace( );
740 if (value[0] == '"') {
741 // The value is a quoted string
742 size_t nextDoubleQuotePosition = value.find('"', 1);
743 if (nextDoubleQuotePosition != kNotFound) {
744 // Store the value as a quoted string without quotes
745 result.append(pair<String, String>(directive, value.substrin g(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
746 pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePo sition + 1;
747 // Move past next comma, if there is one
748 size_t nextCommaPosition2 = safeHeader.find(',', pos);
749 if (nextCommaPosition2 != kNotFound)
750 pos += nextCommaPosition2 - pos + 1;
751 else
752 return; // Parse error if there is anything left with no comma
753 } else {
754 // Parse error; just use the rest as the value
755 result.append(pair<String, String>(directive, trimToNextSepa rator(value.substring(1, value.length() - 1).stripWhiteSpace())));
756 return;
757 }
758 } else {
759 // The value is a token until the next comma
760 size_t nextCommaPosition2 = value.find(',');
761 if (nextCommaPosition2 != kNotFound) {
762 // The value is delimited by the next comma
763 result.append(pair<String, String>(directive, trimToNextSepa rator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
764 pos += (safeHeader.find(',', pos) - pos) + 1;
765 } else {
766 // The rest is the value; no change to value needed
767 result.append(pair<String, String>(directive, trimToNextSepa rator(value)));
768 return;
769 }
770 }
771 } else if (nextCommaPosition != kNotFound && (nextCommaPosition < nextEq ualSignPosition || nextEqualSignPosition == kNotFound)) {
772 // Add directive to map with empty string as value
773 result.append(pair<String, String>(trimToNextSeparator(safeHeader.su bstring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
774 pos += nextCommaPosition - pos + 1;
775 } else {
776 // Add last directive to map with empty string as value
777 result.append(pair<String, String>(trimToNextSeparator(safeHeader.su bstring(pos, max - pos).stripWhiteSpace()), ""));
778 return;
779 }
780 }
781 }
782
783 CacheControlHeader parseCacheControlDirectives(const AtomicString& cacheControlV alue, const AtomicString& pragmaValue)
784 {
785 CacheControlHeader cacheControlHeader;
786 cacheControlHeader.parsed = true;
787 cacheControlHeader.maxAge = std::numeric_limits<double>::quiet_NaN();
788
789 DEFINE_STATIC_LOCAL(const AtomicString, noCacheDirective, ("no-cache", Atomi cString::ConstructFromLiteral));
790 DEFINE_STATIC_LOCAL(const AtomicString, noStoreDirective, ("no-store", Atomi cString::ConstructFromLiteral));
791 DEFINE_STATIC_LOCAL(const AtomicString, mustRevalidateDirective, ("must-reva lidate", AtomicString::ConstructFromLiteral));
792 DEFINE_STATIC_LOCAL(const AtomicString, maxAgeDirective, ("max-age", AtomicS tring::ConstructFromLiteral));
793
794 if (!cacheControlValue.isEmpty()) {
795 Vector<pair<String, String> > directives;
796 parseCacheHeader(cacheControlValue, directives);
797
798 size_t directivesSize = directives.size();
799 for (size_t i = 0; i < directivesSize; ++i) {
800 // RFC2616 14.9.1: A no-cache directive with a value is only meaning ful for proxy caches.
801 // It should be ignored by a browser level cache.
802 if (equalIgnoringCase(directives[i].first, noCacheDirective) && dire ctives[i].second.isEmpty()) {
803 cacheControlHeader.containsNoCache = true;
804 } else if (equalIgnoringCase(directives[i].first, noStoreDirective)) {
805 cacheControlHeader.containsNoStore = true;
806 } else if (equalIgnoringCase(directives[i].first, mustRevalidateDire ctive)) {
807 cacheControlHeader.containsMustRevalidate = true;
808 } else if (equalIgnoringCase(directives[i].first, maxAgeDirective)) {
809 if (!std::isnan(cacheControlHeader.maxAge)) {
810 // First max-age directive wins if there are multiple ones.
811 continue;
812 }
813 bool ok;
814 double maxAge = directives[i].second.toDouble(&ok);
815 if (ok)
816 cacheControlHeader.maxAge = maxAge;
817 }
818 }
819 }
820
821 if (!cacheControlHeader.containsNoCache) {
822 // Handle Pragma: no-cache
823 // This is deprecated and equivalent to Cache-control: no-cache
824 // Don't bother tokenizing the value, it is not important
825 cacheControlHeader.containsNoCache = pragmaValue.lower().contains(noCach eDirective);
826 }
827 return cacheControlHeader;
828 }
829
830 }
OLDNEW
« no previous file with comments | « Source/platform/network/HTTPParsers.h ('k') | Source/platform/network/HTTPParsersTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698